0.0.1 Abbreviation Key

Table 0.1: The full name and abbreviation of all organisms used in this study.
Full Name Abbreviation
Drilaster axillaris D. axillaris
Stenocladuius azuma S. azuma
Cyphonocerus ruficollis C. ruficollis
Lucidina biplagiata Ln. biplagiata
Pyrocoelia miyako Py. miyako
Aquatica lateralis A. Lateralis
Phausis reticulata Pa. reticulata
Luciola cruciata Ll. Cruciata
Lampyris turkestanicus Lp. Turkestanicus
Photinus pyralis Pt. pyralis
Luciola parvula Ll. Parvula
Luciola italica Ll. Italica
Luciola mingrelica Ll. Mingrelica
Phrixothrix hirtus Phr. Hirtus

1 Introduction

     Bioluminescence, or the ability to produce and emit light by a living organism, is thought to be shared across five families of beetles: Elateridae, Lampyridae, Phengodidae, Rhaphthalmidae, and Sinophyrophoridae (Powell et al., 2022). Across these families, research has shown that it has emerged independently twice: once in click beetles (Elateridae) and another time in an ancestor of the lampyroid clade: Lampyridae, Rhagophtalmidae, Sinophyrophoridae, and Phengodidae (Fallon et al., 2018; Kusy et al., 2021; Martin et al., 2017). Furthermore, it is thought to be part of a gene duplication event at a common ancestor of the Lamyridae lineage, implicating that all fireflies have two bioluminescent genes: Luc1 and Luc2 [1.1]. However, so far this Luc2 isotype has only been isolated in Ll. cruciate and Ll. parvula (Bessho-Uehara & Oba, 2017). This duplication allowed for fireflies to develop two different proteins that can be expressed for different needs. It is thought that Luc1 is predominately expressed in larvae, prepupae, pupae, and adults. Due to the match in visual sensitivity of Ll. parvula eyes to that of Luc1, its role is believed to be for intraspecific communication, unlike that of Luc2. Currently, only a few species have had the Luc2 gene isolated, but it is believed that the extant Luc2 is used to express a green glow in the eggs, prepupae, pupae, and adult females of Ll. cruciate and Ll. lateralis (Bessho-Uehara & Oba, 2017).

Molecular phylogeny of luciferases and related enzymes. The leaf nodes are labeled with species name, protein name, and GenBank accession number. Branches are labeled with bootstrap probability (1000 reconstructions). The resurrected ancestral nodes are shown as a square. The leaf nodes are indicated with in vitro luminescent colors (green, yellow-green, yellow, orange, or red) judged by the luminescence maximum values: Green, GR, 520-549 nm; Yellow-green, YG, 550-559 nm; Yellow, YE, 560-584 nm [@obaResurrectingAncientGlow2020].

Figure 1.1: Molecular phylogeny of luciferases and related enzymes. The leaf nodes are labeled with species name, protein name, and GenBank accession number. Branches are labeled with bootstrap probability (1000 reconstructions). The resurrected ancestral nodes are shown as a square. The leaf nodes are indicated with in vitro luminescent colors (green, yellow-green, yellow, orange, or red) judged by the luminescence maximum values: Green, GR, 520-549 nm; Yellow-green, YG, 550-559 nm; Yellow, YE, 560-584 nm (Oba et al., 2020).

     To produce light, the firefly luciferin is converted into an excited state oxyluciferin product (Figure 1.2). Surprisingly, despite all fireflies using the same luciferin substrate, the wavelength emitted varies across the phylum (Branchini et al., 1999b). Typically, fireflies emit a peak emission spectra in vivo between 540-580nm (green to yellow light) (Hall et al., 2016; Navizet et al., 2010; Ugarova & Brovko, 2002). This difference in emission has a couple of different hypothesized reasons in fireflies. The most prominent factor researchers believe to be responsible is that amino acid substitutions in the active sites of Luciferase proteins results in a substantial alteration to a firefly’s peak emission spectra (Branchini et al., 1999b; Morton et al., 1969). Additionally, numerous researchers have shown that site specific amino acid changes results in a shift of the luciferase peak emission wavelength in vitro (Branchini et al., 2001; Shapiro et al., 2005; Wang et al., 2013). However, while these single point mutagenesis models show that these changes do influence the emission spectra emitted by firefly bioluminescence, firefly species have a significant number of mutations across the entire protein. As such, a couple of expected models can be generated. The first is that the entire protein complex matters when determining color, meaning the more amino acid differences between species, the greater the difference in absolute emission spectra. Or, an alternative could be that a firefly’s light emission is dependent on the proteins at specific sites where the enzyme and substrate interact (known as active sites). In this system, it isn’t the total number of changes, but the changes that occur at these active sites that influence the emission color of a firefly.

Mechanism of firefly luciferase catalyzed bioluminescence and TICT excited state of oxyluciferin [@branchini1999].

Figure 1.2: Mechanism of firefly luciferase catalyzed bioluminescence and TICT excited state of oxyluciferin (Branchini et al., 1999b).

     In this paper, I analyze the evolutionary history of Luc1 within a subset of sixteen firefly species to elucidate a potential correlation between the protein structure of each species and the absolute difference in peak emission spectra. First, a phylogenetic tree was generated to determine potential phylogenetic correlation between species of interest and the wavelength emitted. Next, the firefly proteins were analyzed pairwise to determine if a correlation between the absolute difference in peak emission spectra and the differences in three different groups: all amino acids, non-active sites, and only active sites. I found that there is no evolutionary correlation and little, if any, pairwise correlation between these groups and that the peak emission spectra of a firefly is likely determined by a multitude of factors, not just the protein structure.

2 Methods

2.1 Phylogenetics

     Due to the redundancy of genetic code, there are different evolutionary pressures placed on different codon positions. Since the third codon is the least functionally constrained, mutations are more likely to occur there and be passed to the next generation (Bofkin & Goldman, 2007). This becomes a problem when attempting to create a phylogeny of pairwise distances, as these mutations could be cases of convergent evolution, causing improper clustering. As such, sixteen known Luc1 protein sequences (Table 2.1; Supplementary Table 6.1), were imported into Geneious Prime to have the Open Reading Frame (ORF) extracted (for explicit steps see 6.4.1).

Table 2.1: Organisms Studied and supplementary data about each. *Green, GR, 520-549 nm; Yellow-green, YG, 550-559 nm; Yellow, YE, 560-584 nm. (Modified from: Oba et al. (2020))
Species GenBank No. lmax nm Colouration*
Drilaster axillaris AB604790 545 GR
Stenocladius azumai AB644225 545 GR
Cyphonocerus ruficollis AB604789 546 GR
Lucidina biplagiata AB535101 549 GR
Pyrocoelia miyako L39928 550 YG
Aquatica lateralis X66919 552 YG
Phausis reticulata KU600949 552 YG
Luciola cruciata AB220162 554 YG
Lampyris turkestanicus AY742225 555 YG
Photinus pyralis M15077 557 YG
Photinus pyralis AB644228 557 YG
Luciola parvula AB644227 561 YE
Luciola cruciata M26194 562 YE
Luciola italica DQ138966 566 YE
Luciola mingrelica S61961 566 YE
Luciola parvula L39929 568 YE
Phrixothrix hirtus AF139645 622 (pH 8.0) RE

     Next, these ORFs are brought into R to have the first and second codon position removed, leaving only the third codon to be analyzed.

#Import Table.
  ORFs <- read.table("Phylogenetics/ORFs.txt", sep=",", header=FALSE)
#Blank Vector of the final nucleotides.
  only.third <- c() 

#Third Codon Removal.
for (species in ORFs$V2) { 
  #Split the nucleotides into single letter strings. 
    split <- strsplit(species,split = "")
  #Extract the third codon. 
    extracted <- str_remove_all(toString(split[[1]][seq(3, length(split[[1]]), 3)]), ", ")
  #Order of Operations:
    #create a string counting every third position into a new vector, remove those indexes into a new vector.
    #Add the string as a new index.
    only.third <- c(only.third, extracted) 
  
}
#Remove the intermediate vectors made in for-loop.
rm(split, extracted, species)

#Dataframe of the species name and the third codon-only files. 
third.codons.df <- data.frame(ORFs$V1, only.third)


#Modified from: TrainingPizza, 2021
  #Create a vector that can be exported as a .fasta
  third_codons_print <- 
    third.codons.df %>% 
    rowwise() %>%
    pivot_longer(ORFs.V1:only.third) %>%
    select(-name)
  
  #Export the dataframe as a .fasta.
  write.table(third_codons_print,
              file = "Phylogenetics/Thirdcodons_only.fasta",
              col.names = FALSE,
              row.names = FALSE,
              quote = FALSE)

     These third codon-only sequences were imported into BisonNet to construct a phylogenetic tree. Within the program IQ-Tree, ModelFinder Plus was used to determine the best substitution model that fits the nucleotide sequences using Akaike Information Criterion (AIC), removing the potential for convergent evolution to influence the phylogeny (Minh et al., 2019). The chosen model is then used to assemble a tree within IQ-tree. The outgroup, Phr. hirtus (Accession AF139645), was selected as its luciferase protein is known to be derived from the same ancestral luciferase as Lampyridae (Oba et al., 2020). The .treefile was then imported into Geneious Prime and manually color-coded.

#!/bin/bash
#SBATCH -p short # partition (queue)
#SBATCH -N 1 # (leave at 1 unless using multi-node specific code)
#SBATCH -n 8 # number of cores
#SBATCH --mem-per-cpu=32G # memory per core
#SBATCH --job-name="IQtree" # job name
#SBATCH -o slurm.%N.%j.stdout.txt # STDOUT
#SBATCH -e slurm.%N.%j.stderr.txt # STDERR
#SBATCH --mail-user=_____ # address to email
#SBATCH --mail-type=ALL # mail events (NONE, BEGIN, END, FAIL, ALL)
#SBATCH --exclude=hpc-4,hpc-5,hpc-6


#Load module:
module load phylogeny


#Variables:
barcode=/home/arb027/CAPSTONE/ThirdCodon_alignment.fasta #The input file.
merit=AIC #Akaike Information Criteria Metric for IQ-Tree ModelFinder Plus.
outgroup=RE_Phr_hirtus_AF139645_2 #Sequence Identifier of the outgroup.
bootstrap=10000 #Number of bootstraps. 

#Print variables to console (for user references):
cat <<OPTIONS
Alignment file: $barcode
Search for the best model of sequence evolution using: $merit
Outgroup: $outgroup
Number of Bootstraps: $bootstrap
OPTIONS

#IQtree:
    #Documentation: http://www.iqtree.org/doc/Command-Reference
iqtree -s $barcode -merit $merit -o $outgroup  -bb $bootstrap

#Unload module:
module unload phlogeny 

2.2 R Analysis

     The original nucleotide ORFs for the firefly proteins (were translated into protein sequences and aligned using MUSCLE (algorithm PPP, HMM Pertubations = 0, Guide Tree Purmutations = 0) in Geneious Prime to be imported into R. While 17 Luc1 proteins have previously been identified by Oba et al. (2020) and were used to construct the phylogenetic tree, the Pt. pyralis Luc1 mRNA (Accession: M15077) only has 182 amino acids, while the other proteins have around 560 proteins. Additionally, later analysis looks into known active sites of the Luc1 protein using data from Pt. Pyralis, where the first known active site is at AA position 197. Even when aligned with MUSCLE, a significant majority of the outlined active sites are not aligned with the other proteins (Supplementary Figure 6.2. Further research into this mRNA protein would be required to determine where the active sites are located within this specific protein. However, there is another known luc1 mRNA protein for Pt. pyralis (Accession: AB644228) that does properly align to other proteins (Supplementary Materials 6.2). By looking across the previously outlined categories in Supplementary Figure 6.1 (Green, GR, 520-549 nm; Yellow-green, YG, 550-559 nm; Yellow, YE, 560-584 nm), these proteins, along with the emission spectra of each species at a pH of 7.8, were then analyzed to determine the absolute pairwise distance between each species’ emission spectra.

     To determine the total amino acid differences, the package stringdist was used to create a pairwise distance matrix at each amino acid site using the Hamming Distance Metric: “count the number of character substitutions that turns b into a, if a and b have different number of characters the distance is Inf” (Loo, 2014). For those curious towards the analysis protocol used, see 6.4.2.

  align.vector <- as.vector(proteins$aligned)
#Determine the total length of the aligned proteins vector.
  sites <- nchar(align.vector[1])
  
  
  
#Matrix of all amino acid sites
  sum.all.matrix <- as.matrix(stringdistmatrix(align.vector, method = "hamming"))

#Names. 
colnames(sum.all.matrix) <- proteins$Name
rownames(sum.all.matrix) <- proteins$Name

#Matrix to df.
sum.all.df <- melt(sum.all.matrix, varnames = c("Species1", "Species2"))
#Name Column. 
colnames(sum.all.df)[3] <- "AllDiff"

#Merge into the master dataframe. 
combined.df <- merge(combined.df, sum.all.df)

     A similar method was employed for both calculating the number of differences excluding the amino acid active sites and a separate 3-D matrix for only the active sites. The active sites for Pt. Pyralis have previously been identified by Leach (2008, Table 6.2). During alignment, ten sites were added to the Pt. Pyralis protein (Supplementary Figure 6.2), so these active sites were mutated by ten for analysis.

#Active site Table
  activesites.table <- read_excel("Supplementary Materials.xlsx", sheet = "ST2", )
#Table to vector including adjusting for alignment (+10).
  activesites <- activesites.table$Site + 10 

     To analyze the number of amino acid differences excluding the active sites, a modified version of stringdistmatrix was used to create a vector of all 522 amino acids that are not known active sites. For each index of the vector, a pairwise distance was then calculated, giving a matrix of 0s and 1s, where 0 indicates no difference and 1 equals a difference at the specific site. As each site was calculated, it was mutated to a three dimensional matrix along the z-axis, giving a 15x15x521 matrix. This matrix was then summed down the z axis to give the total number of differences between each species luciferase protein (See 6.4.2.2 for a detailed breakdown of matrix dimensionality with visualization).

#Get a vector of the total number of amino acid sites. 
  sites <- c(1:nchar(align.vector[1]))

# Create the first pairwise matrix. 
  all.Distmatrix1 <- as.matrix(stringdistmatrix(str_sub(align.vector, 1, 1), method = "hamming")) 
  #Order of Operations:
  #str_sub: Create a vector of the protein at the first active site. 
  #stringdistmatrix: Does a simple comparison matrix between each group (0 = identical, 1 = difference) using Hamming methodology (counts the number of character substitutions that turns b into a. If a and b have different number of characters the distance is Inf [If a string has a length greater than 1 it causes an error, making this self checking]).
#Remove both the first site that was analyzed and all of the active sites. 
  sites <- sites[-c(1, activesites)]

#Create the array using the first matrix.
  noactive.matrix <- array(data=c(all.Distmatrix1), dim = c(length(align.vector), length(align.vector),1))

#Loop all the sites selected. 
  for (site in sites) { 
    #Same logic as the first matrix.
      single <- as.matrix(stringdistmatrix(str_sub(align.vector, site, site), method = "hamming"))
     #Append the new matrix along the z axis.
      noactive.matrix <- abind(single, noactive.matrix, along = 3)
}

#Add up the total number of differences between each protein by summing down the z axis (dims = 2).
  sum.noactive.matrix <- as.matrix(rowSums(noactive.matrix, dims = 2)) 

#Names. 
  colnames(sum.noactive.matrix) <- proteins$Name
  rownames(sum.noactive.matrix) <- proteins$Name

#matrix to df.
  sum.noactive.df <- melt(sum.noactive.matrix, varnames = c("Species1", "Species2"))
#Name Column. 
  colnames(sum.noactive.df)[3] <- "NoActiveDiff"

#Merge to master. 
  combined.df <- merge(combined.df, sum.noactive.df)

     A similar pairwise distance metric was then used but instead of analyzing the amino acids without the active sites, this time the 3D matrix was created only at the active sites, creating a 15x15x43 pairwise matrix that was then summed along the z axis. This matrix was then mutated into a dataframe for analysis (See 6.5 for visualization).

#Create the first matrix 
  activesites.Distmatrix1 <- as.matrix(stringdistmatrix(str_sub(align.vector, activesites[[1]], activesites[[1]]), method = "hamming")) 
#Order of Operations:
  #str_sub: Create a vector of the protein at the first active site. 
  #stringdistmatrix: Does a simple comparison matrix between each group (0 = identical, 1 = difference) using Hamming methodology (counts the number of character substitutions that turns b into a. If a and b have different number of characters the distance is Inf [If a string has a length greater than 1 it causes an error, making this self checking]).
  
#Remove the analyzed site from the vector to prevent repeat analysis. 
  activesites <- activesites[-1]

#Create the array using the first matrix as our input data. 
  activesites.matrix <- array(data=c(activesites.Distmatrix1), dim = c(length(align.vector), length(align.vector),1))

  
#Looping all the matrix sites. 
for (site in activesites) { 
#Same as the first matrix. 
  single <- as.matrix(stringdistmatrix(str_sub(align.vector, site, site), method = "hamming")) 
#Append the new matrix along the z axis to the 3D array. 
  activesites.matrix <- abind(single, activesites.matrix, along = 3) 
}

#Distance matrix summed.
  activesites.dist.all.matrix <- rowSums(activesites.matrix, dims = 2)
  #Add up the total number of differences between each protein by summing down the z axis (dims = 2).

#Distance output
  activesites.dis.all.dist <- as.dist(rowSums(activesites.matrix, dims = 2)) 
  #This is for user reference, it is not analyzed by the script. 

#Name the Matrix. 
  colnames(activesites.dist.all.matrix) <- proteins$Name
  rownames(activesites.dist.all.matrix) <- proteins$Name

#matrix -> dataframe. 
  activesites.dist.all.df <- melt(activesites.dist.all.matrix, varnames = c("Species1", "Species2"))
#Name the new column
  colnames(activesites.dist.all.df)[3] <- "ActiveSitesOnly"

#Merge this dataframe with the master dataframe. 
  combined.df <- merge(combined.df, activesites.dist.all.df)

     The dataframe containing the species compared, the emission spectra, and the number of differences at the three groups was then cleaned to remove any self comparisons and duplicate comparisons created during the conversion from a matrix to dataframe.

#Logic found at:https://stackoverflow.com/questions/23474729/convert-object-of-class-dist-into-data-frame-in-r
#Remove Duplicates and 
  #Sort the two columns.
    names <- t(apply(combined.df[,c(1,2)],1,FUN=sort)) 
  #Find rows comparing the same organism. 
    same <- which(names[,1] == names[,2]) 
  #Merge names columns into single column separated by |.
    names    <- paste(names[,1],names[,2],sep="|") 
  #find duplicate comparisons.
    dups <- which(duplicated(names)) 
  # Remove any same organism or duplicates 
  combined.df <- combined.df[-c(same, dups),] 

rm(dups, names, same)

combined.df$Species1 <- gsub('_', ' ', combined.df$Species1)
combined.df$Species2 <- gsub('_', ' ', combined.df$Species2)

#Only get the wavelength emission spectra of the species
combined.df$Species1.abr <- str_sub(combined.df$Species1, 1,2)
combined.df$Species2.abr <- str_sub(combined.df$Species2, 1,2)


#Abr col comparison
combined.df$Comparison.abr <- str_c(combined.df$Species1.abr, "/", combined.df$Species2.abr)
#Full Name Comparison
combined.df$Comparison.full <- str_c(combined.df$Species1, "/", combined.df$Species2)


#organize the comparisons from green to yellow. 
combined.df$Comparison.abr <- factor(combined.df$Comparison.abr, levels = c("GR/GR", "GR/YE", "GR/YG", "YG/YG", "YE/YG", "YE/YE"))



colors <- c("#074000", "#aeff17", "#66db00", "#699647", "#26b530", "blue")

     Finally, these pairwise comparisons were graphed using a combination of ggplot2 (Wickham et al., 2023), gplots (Warnes et al., 2022), and plotly (Sievert et al., 2022) to create both heatmaps of the summed differences and scatterplots comparing the absolute change in emission spectra vs. the difference in amino acid residues. For a visualized workflow, see 6.1.

3 Results

3.1 Phylogenetics

After extracting the third codon only and running IQ-tree, a maximum likelihood tree was built using GTR+F+G4 as the selected substitution model. As shown in Figure 3.1, no monophyletic grouping was established between different color categories. Furthermore, the two Li. cruciata group together into a unique clade, despite having different emission spectra. While this tree does have low bootstrap support values, it has similar branching to that of Oba et al. (2020), providing support to the evolutionary history of this tree.

Phylogenetic tree of the analyzed species (Bootstraps = 10,000, metric = AIC), Color-coding manually mutated.

Figure 3.1: Phylogenetic tree of the analyzed species (Bootstraps = 10,000, metric = AIC), Color-coding manually mutated.

3.2 Pairwise Distance Analysis

The three different arrays were summed along the z axis into three 2-dimensional matrices, which were then plotted as a heatmap and against the absolute difference in emission spectra:

heatmap.2(sum.all.matrix, 
          Rowv = FALSE, 
          Colv = FALSE, 
          dendrogram = "none", 
          symm = TRUE, 
          scale = "none", 
          trace = "none", 
          margins = c(11.5,10), 
          cellnote = sum.all.matrix,
          notecol = "black", 
          cexRow = 0.7
          )
Heatmap displaying the total number of amino acid differences between each species.

Figure 3.2: Heatmap displaying the total number of amino acid differences between each species.

sum.all.plot <- ggplot(combined.df, 
                                  aes(x = abs.emission.diff,
                                      y=AllDiff, 
                                      color=Comparison.abr, 
                                      label = Comparison.full,
                                      shape=Comparison.abr)) + 
  geom_point() + 
  theme_classic() + 
  stat_ellipse() + 
  scale_color_manual(values = colors) +
  xlab("Absolute ∆ Emission Spectra") +
  ylab("Total Number of AA Differences") + 
  labs(color = "Comparison Group", shape = "Comparison Group")
  
#Interactive plot
  ggplotly(sum.all.plot) 

Figure 3.3: Interactive scatter-plot of the absolute change in emission spectra vs. the total number of amino acid differences between each species.

heatmap.2(sum.noactive.matrix, 
          Rowv = NA, 
          Colv = NA, 
          dendrogram = "none", 
          symm = TRUE, 
          scale = "none", 
          trace = "none", 
          margins = c(11.5,10), 
          cellnote = sum.noactive.matrix, 
          notecol = "black", 
          cexRow = 0.7
          )
Heatmap displaying the total number of amino acid differences, excluding active sites, between each species.

Figure 3.4: Heatmap displaying the total number of amino acid differences, excluding active sites, between each species.

#ggplot2 - All aesthetics are self-explainatory. 
sum.noactive.plot <- ggplot(combined.df, 
                                  aes(x = abs.emission.diff,
                                      y=NoActiveDiff, 
                                      color=Comparison.abr, 
                                      label = Comparison.full,
                                      shape=Comparison.abr)) + 
  geom_point() + 
  theme_classic() + 
  stat_ellipse() + 
  scale_color_manual(values = colors) +
  xlab("Absolute ∆ Emission Spectra") +
  ylab("Total Number of AA Differences w/o Active Sites") +
  labs(color = "Comparison Group", shape = "Comparison Group")
  
#Interactive plot.
  ggplotly(sum.noactive.plot) 

Figure 3.5: Interactive scatter-plot of the absolute change in emission spectra vs. the total number of amino acid differences, excluding active sites, between each species.

heatmap.2(activesites.dist.all.matrix, 
          Rowv = NA, 
          Colv = NA, 
          dendrogram = "none", 
          symm = TRUE, 
          scale = "none", 
          trace = "none", 
          margins = c(11.5,10), 
          cellnote = activesites.dist.all.matrix, 
          notecol = "black", 
          cexRow = 0.7
          )
Heatmap displaying the total number of active site amino acid differences between each species.

Figure 3.6: Heatmap displaying the total number of active site amino acid differences between each species.

sum.activeonly.plot <- ggplot(combined.df, 
                                  aes(x = abs.emission.diff,
                                      y=ActiveSitesOnly, 
                                      color=Comparison.abr, 
                                      label = Comparison.full,
                                      shape=Comparison.abr)) + 
  geom_point() + 
  theme_classic() + 
  stat_ellipse() + 
  scale_color_manual(values = colors) +
  xlab("Absolute ∆ Emission Spectra") +
  ylab("Total Number of Active Sites AA differences") +
  labs(color = "Comparison Group", shape = "Comparison Group")
  
#Interactive plot
  ggplotly(sum.activeonly.plot) 

Figure 3.7: Interactive scatter-plot of the absolute change in emission spectra vs. the total number of active site amino acid differences, excluding active sites, between each species.

     Across all of these figures, no correlation between the emission spectra emitted and the number of amino acid differences could be elucidated. The intracomparisons of the yellow group reveals that despite the Ll. cruciata having a maximum difference in emission spectra of 8nm (Ll parvula, 568nm), this species has over 100 total amino acid differences between each other yellow species. This is in sharp contrast to other intra-color specie comparisions who only have between 6 and 28 total amino acid differences. Additionally, when brought to the level of active sites, the yellow species had 0 differences in amino acid residues, with the exception of Ll. cruciata with 2 differences. In other words, all of the amino acid differences were found in areas that are not directly interacting with the luciferin substrate.

     Of particular interest are 2 Li. cruciata Luc1, one that emits a peak wavelength of 565nm (yellow, Accession #M26194), and the other which emits a peak wavelength of 554 (yellow-green wavelength, Accession #AB220162). While most other species have multiple amino acid differences at both all amino acids and the active sites, these two species have only 5 amino acid differences at non-active sites, and an absolute change in peak emission spectra of 7.

     For the other color categories, while the intra-comparisons have a slightly lower number of differences than inter-group comparisons, there is still a high degree of differences in emission spectra. Even when accounting for just active sites, there is even less of a correlation as each group was highly overlapping with each other. Furthermore, there are a couple of comparisons where despite having no difference in peak emission wavelength, there is a difference in amino acid residues. Collectively, these graphs show that the amino acid residues are not the most significant contribution towards the color emission emitted during bioluminescence.

4 Discussion

     Phylogenetically, this data shows that there is no evolutionary correlation to the wavelength spectra emitted by a firefly. Comparing this tree to that of Oba et al. (2020) (Figure 1.1), it is interesting to see the species are grouping similarly along the phylogenetic lineage, despite Oba et al. undergoing a difference series of steps and using a different substitution model (JTT matrix vs GTR+F+G4). Since the mutations undertaken removed the possibility of convergent evolution, this data suggests that evolutionarily, the amino acid residues present within a species are not a primary determinant of the color spectra emitted. If this were the case, it would be expected to see the tree start with red (the designated outgroup color) and have monophyletic clades of yellow, yellow-green, and green, identical to that of the color spectrum.

     These conclusions are further backed by the heat-maps and scatter-plots showing little to no correlation between the number of amino acid differences and the absolute change in peak emission spectra. In fact, the results of the whole protein and without active site analysis suggests that despite having a high number a high number of differences in amino acid residues across the whole protein, there is a small change in the absolute emission spectra between comparison colors.

     Furthermore, the intra- and inter-categorical comparisons having a large number of differences in amino acid residues despite having a small change in peak emission spectra suggests that a significant portion of the amino acid residues do not play a role in the emission spectra a species emits. However, further testing would be required to support this hypothesis.

     Looking into active sites, the yellow wavelength category having 0 active site differences, with the exception of Ll. cruciata which has 2 differences, despite continuing to have a difference in peak emission spectra. While this subset suggests that the residues at an active site could play some role in the wavelength emitted by a species, as indicated by the differences in amino acid residues when compared to other color groups, the other categories reject this by Ll. cruciata (yellow), having no active site differences to Ll. cruciata (yellow-green) and A. lateralis, despite having an absolute change in emission spectra of 8 and 10 respectively.

     There is even less of a correlation with each group being highly spread across the scatterplot and not clustering into distinct groups or along a linear model as predicted. These few, if any, number of differences across over 40 amino acid active sites indicates that these sites could likely be under some form of constraint to enable bioluminescence within the firefly, however further testing would be necessary to confirm such possibilities.

     Alternatively, it could be that the number of changes is not what matters, but the specific amino acid present. As previously stated, single point mutagenesis studies have shown the affect a single amino acid residue can have on the emission spectra of a luciferase protein (Branchini et al., 2001; Shapiro et al., 2005; Wang et al., 2013). Additionally, it has been found that the wavelength emitted by a luciferase enzyme is dependent on pH (Viviani et al., 2018). Furthermore, Zhao et al. (2005) showed that by increasing the temperature of luciferase, the brightness and emission spectra is redshifted. Since majority of these samples were collected in the field, the temperature at the time of collection would skew the true peak emission spectra of a species luciferase. Finally, the luciferase reaction occurs internally, meaning any light emitted by a firefly must travel through the body of the firefly before being detected by either a machine or human eyes. It is highly plausible that the depth at which the luciferase reaction occurs and the composition of the cuticle plays a significant role in the emission spectra seen by fireflies. Despite luciferase being prominently used in biology and the medical industry for bioluminescent imaging, no research was found on the effect of either parameter on the emission spectra of luciferase, leaving this hypothesis unconfirmed.

5 Conclusions

     This study was unable to support the hypothesis that the number of amino acid differences (whether that be across the entire protein or at a protein’s active sites) does conclusively determine the wavelength spectra emitted by a firefly. While these differences might play some role, as supported by mutagenesis studies, it is much likely to be a combination of variables that alter the emission spectra emitted. This means that while the differences could play some role, the current datasets and analysis do not allow for conclusive testing towards the exact relationship different amino acids at various positions play in firefly bioluminescence. Furthermore, in order to elucidate the true correlation between all factors (pH, temperature, filtration, etc.), even more extensive research would need to be done to allow for both detection within the light organ itself, and later isolation of the luciferase compound for further study. Although none of these are likely to be seen anytime soon, this study does enable future researchers to begin to understand the influence of amino acid residues and act as a springboard to higher analysis and investigation.

6 Supplementary Files

6.1 Data Availability

All files used in this project is available within respective folders in the project directory.

     For users wishing to replicate any code chunks, all required libraries can be installed running the included Package.Installer.R file. Otherwise, downloading and editing this .Rmd file has the necessary commands built-in to install any missing packages. However, it is HIGHLY advised that only those with a solid understanding of R attempt to alter any functions or code chunks.

6.2 Tables

6.2.1 Supplemental Table 1

Table 6.1: Organisms Studied and supplementary data about each. **Green, GR, 520-549 nm; Yellow-green, YG, 550-559 nm; Yellow, YE, 560-584 nm. (Modified from: Oba et al. (2020))
Family Subfamily Species Origin GenBank No. Gene name Sex if known lmax nm Colouration* Reference
Lampyridae Ototretinae Drilaster axillaris Japan AB604790 DaLuc1 (Luc1 luciferase) Unknown 545 GR (Oba et al., 2012)
Lampyridae Ototretinae Stenocladius azumai Japan AB644225 SaLuc1 (Luc1 luciferase) Unknown 545 GR (Oba et al., 2012)
Lampyridae Cyphonocerinae Cyphonocerus ruficollis Japan AB604789 CrLuc1 (Luc1 luciferase) Unknown 546 GR (Oba et al., 2012)
Lampyridae Lampyrinae Lucidina biplagiata Japan AB535101 LbLuc1 (Luc1 luciferase) Unknown 549 GR (Oba et al., 2012)
Lampyridae Lampyrinae Pyrocoelia miyako Japan L39928 NA Unknown 550 YG (Ohmiya et al., 1995)
Lampyridae Luciolinae Aquatica lateralis Japan X66919 LlLuc1 (Luc1 luciferase) Unknown 552 YG (Tatsumi et al., 1989)
Lampyridae Lamprohizinae Phausis reticulata USA KU600949 NA Male (in vivo) 552 YG (Branchini et al., 2017)
Lampyridae Luciolinae Luciola cruciata Japan AB220162 LcLuc1 (Luc1 luciferase) Male (in vivo) 554 YG (Oba et al., 2010)
Lampyridae Lampyrinae Lampyris turkestanicus Middle East AY742225 NA Unknown (Combination of both male and female cDNA) 555 YG (Tafreshi et al., 2008)
Lampyridae Lampyrinae Photinus pyralis USA M15077 PpyLuc1 (Luc1 luciferase) In vitro 557 YG (Branchini et al., 2007)
Lampyridae Lampyrinae Photinus pyralis USA AB644228 PpyLuc1 (Luc1 luciferase) In vitro 557 YG (Branchini et al., 2007)
Lampyridae Luciolinae Luciola parvula Japan AB644227 LpLuc1 (Luc1 luciferase) Unknown 561 YE (Oba et al., 2012)
Lampyridae Luciolinae Luciola cruciata Japan M26194 NA Unknown 562 YE (Kajiyama & Nakano, 1991)
Lampyridae Luciolinae Luciola italica Italy DQ138966 NA Unknown 566 YE (Branchini et al., 2006)
Lampyridae Luciolinae Luciola mingrelica Eastern Europe S61961 NA Unknown 566 YE (Koksharov & Ugarova, 2008)
Lampyridae Luciolinae Luciola parvula Japan L39929 NA Male (in vitro) 568 YE (Ohmiya et al., 1995)
Phengodidae Phrixothrix hirtus USA AF139645 PhRE Unknown 622 (pH 8.0) RE (Cloning, Sequence Analysis, and Expression of Active Phrixothrix Railroad-Worms Luciferases, n.d.)

6.2.2 Supplemental Table 2

Table 6.2: Active Sites used in this study (Modified from: Leach (2008))
Site AA Reference
197 N (Branchini et al., 1998, 2000)
198 S (Branchini et al., 1999b; Conti et al., 1996; Sandalova & Ugarova, 1999)
199 S (Branchini et al., 1999c, 1999b), web
206 K (Conti et al., 1996), web
218 R (Branchini et al., 2003, 1998, 2000, 2004; Branchini, Magyar, Murtiashaw, et al., 1997; Sandalova & Ugarova, 1999; Ugarova & Sandalova, 1998; Viviani et al., 2002), web
244 H (Branchini et al., 1999a; Branchini, Magyar, Murtiashaw, et al., 1997; Branchini, Magyar, Marcantonio, et al., 1997)
245 H (Branchini, Magyar, Marcantonio, et al., 1997; Branchini et al., 1998, 1999b, 2000, 2004; Sandalova & Ugarova, 1999). web
246 G (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2004)
247 F (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini, Magyar, Marcantonio, et al., 1997; Branchini et al., 1998, 1999b, 2000, 2004; Franks et al., 1998; Sandalova & Ugarova, 1999, 1999; Viviani et al., 2002), web
250 F (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 1998, 1999b, 2004)
251 T (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2004)
310 H (Franks et al., 1998)
311 E (Franks et al., 1998)
313 A (Franks et al., 1998)
314 S (Ugarova & Sandalova, 1998)
315 G (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2004; Franks et al., 1998; Sandalova & Ugarova, 1999)
316 G (Branchini et al., 2004; Sandalova & Ugarova, 1999)
317 A (Branchini et al., 1998; Sandalova & Ugarova, 1999), web
318 P (Sandalova & Ugarova, 1999)
337 R (Sandalova & Ugarova, 1999)
338 Q (Sandalova & Ugarova, 1999)
339 G (Branchini et al., 1998, 2000; Sandalova & Ugarova, 1999, 1999), web
340 Y (Branchini et al., 1999a, 1998; Conti et al., 1996; Sandalova & Ugarova, 1999), web
341 G (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2004; Sandalova & Ugarova, 1999),web
342 L (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2004)
343 T (Branchini et al., 1999a, 1998, 2004; Branchini, Magyar, Murtiashaw, et al., 1997; Sandalova & Ugarova, 1999), web
344 E (Conti et al., 1996; Sandalova & Ugarova, 1999)
347 S (Branchini et al., 1998, 2000, 2004; Sandalova & Ugarova, 1999, 1999), web
348 A (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 1998, 2000, 2004; Sandalova & Ugarova, 1999)
351 I (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2004; Sandalova & Ugarova, 1999)
352 T (Franks et al., 1998)
353 P (Franks et al., 1998)
354 E (Franks et al., 1998)
389 E (Conti et al., 1996)
401 Y (Conti et al., 1996)
417 W (Dementieva et al., 2000)
420 S (Conti et al., 1996)
421 G (Conti et al., 1996)
422 D (Branchini et al., 2004; Conti et al., 1996; Sandalova & Ugarova, 1999), web
434 I (Sandalova & Ugarova, 1999)
437 R (Leach, 2008)
527 T (Sandalova & Ugarova, 1999)
529 K (Branchini, Magyar, Murtiashaw, et al., 1997; Branchini et al., 2000, 2004; Sandalova & Ugarova, 1999, 1999), web

6.3 Figures

6.3.1 Supplementary Figure 1

Workflow

Figure 6.1: Workflow

6.3.2 Supplemental Figure 2

MUSCLE Alignment Data, of particular note is the misalignment to the active sites of the *Pt. pyralis* Luc1 (Accession: M15077), which was further excluded from analysis due to the presence of a second known Luc1 protein for *Pt. pyralis*

Figure 6.2: MUSCLE Alignment Data, of particular note is the misalignment to the active sites of the Pt. pyralis Luc1 (Accession: M15077), which was further excluded from analysis due to the presence of a second known Luc1 protein for Pt. pyralis

6.4 Supplemental Code:

6.4.1 Geneious Prime ORF Extraction

## Step (File Path): 
##  1. Download sequences from GenBank.
##  2. Import the Raw Luciferase Proteins (SupplementaryFiles/Luciferase_raw_sequences.fasta).
##  3. Identify the ORFs and export into a new file (SupplementaryFiles/Luciferase_ORFs.fasta). 
##  4. Exported as .txt file for analysis (Phylogenetics/ORFs.txt). 
##  a. The .txt file was chosen as it allowed for less manual mutations to alter into a csv than the built in .csv export function in Geneious Prime.
## 

6.4.2 Pairwise Distance Matrix

6.4.2.1 Logic

     Below is the logic used by the stringdistmatrix function in the package stringdist that I wrote while determining how to only analyze the active sites. From a precursory glance using getAnywhere() and other source code viewing functions, the way stringdist integrates is much more compact and uses functions that are faster when used in R, but comes at the cost of being difficult to replicate and explain to others who have an introductory level in computer science. As such, I wrote my own version that creates a comparison matrix at each site, allowing for easy visualization to a non-computer scientist. For each cell in the matrix, a 0 indicates the proteins are identical between two species (indicated by row and column name), while a 1 indicates the proteins are different. Since these proteins were aligned, the Hamming method was chosen to act as an alignment checker since if string A does not have the same length as String B, the result is Infinite which causes later code to fail. Each matrix is then aligned into a three dimensional matrix to be summed down the z axis for the total number of differences These 3D arrays were then summed across each cell to determine the total distance between each Luc1 protein, which were then plotted.

#Prevents redundancy of vector creation.
  align.vector <- as.vector(proteins$aligned)
#Determine the total length of the aligned proteins vector.
  sites <- nchar(align.vector[1])
  
#Create first matrix. 
  all.Distmatrix1 <- as.matrix(stringdistmatrix(str_sub(align.vector, 1, 1), method = "hamming")) 
    #Order of Operations:
      #str_sub: Create a vector of the protein at only the first site. 
      #stringdistmatrix: Does a simple comparison matrix between each group (0 = identical, 1 = difference) using Hamming methodology [If a string has a length greater than 1 it causes an error, making this self checking].

#Create the array using the first matrix
  all.matrix <- array(data=c(all.Distmatrix1), dim = c(length(align.vector), length(align.vector),1))


#Repeat the matrix for all other sites within the protein
for (site in 2:sites) { 
  single <- as.matrix(stringdistmatrix(str_sub(align.vector, site, site), method = "hamming"))#Same as first matrix
  all.matrix <- abind(single, all.matrix, along = 3) #Append the new matrix along the z axis.
}

#Summed Matrix. 
  sum.all.matrix <- as.matrix(rowSums(all.matrix, dims = 2))
  #Add up the total number of differences between each protein by summing down the z axis (dims = 2).
  
#Names. 
colnames(sum.all.matrix) <- proteins$Name
rownames(sum.all.matrix) <- proteins$Name

#matrix to df
sum.all.df <- melt(sum.all.matrix, varnames = c("Species1", "Species2"))
colnames(sum.all.df)[3] <- "AllDiff"

#Merge into the master dataframe. 
combined.df <- merge(combined.df, sum.all.df)

6.4.2.2 Visualization

     Similar to a chess board, a pairwise matrix is defined into cells that can be indexed based on the row and column number/letter. For instance, in chess the index [D4] corresponds to the cell at the fourth column (D), fourth row of the chess board (4) (Figure 6.3). Similarly, the index of a matrix corresponds to a specific point based upon the row and then the column (meaning [2,1] is the second row, first column).

An example chessboard and matrix [@HowSetChessboard].

Figure 6.3: An example chessboard and matrix (How to Set up a Chessboard - A Quick & Simple Guide, n.d.).

An example chessboard and matrix [@lancashire3000MappingTensorNotation2022].

Figure 6.4: An example chessboard and matrix (Lancashire3000, 2022).

     In a pairwise distance matrix, the row and column represent a specific species, and the cell represents the result of a comparison between the two. In this study, that comparison is two things: the emission spectra, and the amino acid residue at specific sites. For the emission spectra, this is taken using the absolute difference between the species.

The absolute difference in emission between each species.

Figure 6.5: The absolute difference in emission between each species.

     On the other hand, since the proteins are letters instead of numbers, a binary system must be used in which the differences are either 0s (indicating identical amino acid residues) or 1s (indicating a difference in amino acid residues). However, this only gives the differences at one point. Therefore, when doing a pairwise difference across the entire protein, a pairbased matrix must be created at each point. In order to not have a unique vector for each matrix, we can use 3-dimensional arrays in which one matrix (a chessboard) is stacked on top of another matrix (Figure 6.6). This array is then summed through the z-axis to produce a single matrix with the total number of differences between each species.

Visual demonstration of stacking matrices to create a 3-dimensional matrix.

Figure 6.6: Visual demonstration of stacking matrices to create a 3-dimensional matrix.

6.5 Matrix to Dataframe

Take the distance matrix:

values <- c(0,1,2,3,4,5)

matrix <- abs(diffmat(values))
matrix 
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    0    1    2    3    4    5
## [2,]    1    0    1    2    3    4
## [3,]    2    1    0    1    2    3
## [4,]    3    2    1    0    1    2
## [5,]    4    3    2    1    0    1
## [6,]    5    4    3    2    1    0

Using the melt function, we get the output below, where the row represents the first column, the column recommends the second column, and the distance value represents the third column.

##    Row Column Value
## 1    1      1     0
## 2    2      1     1
## 3    3      1     2
## 4    4      1     3
## 5    5      1     4
## 6    6      1     5
## 7    1      2     1
## 8    2      2     0
## 9    3      2     1
## 10   4      2     2
## 11   5      2     3
## 12   6      2     4
## 13   1      3     2
## 14   2      3     1
## 15   3      3     0
## 16   4      3     1
## 17   5      3     2
## 18   6      3     3
## 19   1      4     3
## 20   2      4     2
## 21   3      4     1
## 22   4      4     0
## 23   5      4     1
## 24   6      4     2
## 25   1      5     4
## 26   2      5     3
## 27   3      5     2
## 28   4      5     1
## 29   5      5     0
## 30   6      5     1
## 31   1      6     5
## 32   2      6     4
## 33   3      6     3
## 34   4      6     2
## 35   5      6     1
## 36   6      6     0

However since the diagonal of the matrix is a self comparison, this would not be an apt comparison. So these values can be removed with the simple logic function:

#Extract columns 1 and 2 from the master dataframe:
df.names <- t(apply(df[,c(1,2)],1,FUN=sort)) 

#Find rows where the number in column one is identical to the number in column two. 
    df.same <- which(df.names[,1] == df.names[,2]) 
  
df <- df[-(df.same),]
df
##    Row Column Value
## 2    2      1     1
## 3    3      1     2
## 4    4      1     3
## 5    5      1     4
## 6    6      1     5
## 7    1      2     1
## 9    3      2     1
## 10   4      2     2
## 11   5      2     3
## 12   6      2     4
## 13   1      3     2
## 14   2      3     1
## 16   4      3     1
## 17   5      3     2
## 18   6      3     3
## 19   1      4     3
## 20   2      4     2
## 21   3      4     1
## 23   5      4     1
## 24   6      4     2
## 25   1      5     4
## 26   2      5     3
## 27   3      5     2
## 28   4      5     1
## 30   6      5     1
## 31   1      6     5
## 32   2      6     4
## 33   3      6     3
## 34   4      6     2
## 35   5      6     1

Additionally, a comparison of #1 v. #2 is going to produce the same value as the comparison #2 v. #1 since a matrix is symmetrical down the diagonal. As such, these values need to be removed for comparison:

#Merge names columns into single column separated by |.
    df.names <- paste(df.names[,1],df.names[,2],sep="|") 
  #find duplicate comparisons.
    df.dups <- which(duplicated(df.names)) 
df <- df[-(df.dups),]
df
##    Row Column Value
## 2    2      1     1
## 3    3      1     2
## 4    4      1     3
## 5    5      1     4
## 6    6      1     5
## 7    1      2     1
## 10   4      2     2
## 11   5      2     3
## 12   6      2     4
## 13   1      3     2
## 14   2      3     1
## 18   6      3     3
## 19   1      4     3
## 20   2      4     2
## 21   3      4     1
## 26   2      5     3
## 27   3      5     2
## 28   4      5     1
## 34   4      6     2
## 35   5      6     1

References

Amos, J. (2018). Answer to "vector to matrix of differences between elements". https://stackoverflow.com/a/50882674
Bessho-Uehara, M., & Oba, Y. (2017). Identification and characterization of the Luc2-type luciferase in the Japanese firefly, Luciola parvula, involved in a dim luminescence in immobile stages. Luminescence: The Journal of Biological and Chemical Luminescence, 32(6), 924–931. https://doi.org/10.1002/bio.3273
Bofkin, L., & Goldman, N. (2007). Variation in Evolutionary Processes at Different Codon Positions. Molecular Biology and Evolution, 24(2), 513–521. https://doi.org/10.1093/molbev/msl178
Branchini, B. R., Ablamsky, D. M., Rosenman, J. M., Uzasci, L., Southworth, T. L., & Zimmer, M. (2007). Synergistic mutations produce blue-shifted bioluminescence in firefly luciferase. Biochemistry, 46(48), 13847–13855. https://doi.org/10.1021/bi7015052
Branchini, B. R., Magyar, R. A., Marcantonio, K. M., Newberry, K. J., Stroh, J. G., Hinz, L. K., & Murtiashaw, M. H. (1997). Identification of a firefly luciferase active site peptide using a benzophenone-based photooxidation reagent. Journal of Biological Chemistry, 272(31), 19359–19364.
Branchini, B. R., Magyar, R. A., Murtiashaw, M. H., Anderson, S. M., Helgerson, L. C., & Zimmer, M. (1999a). Site-Directed Mutagenesis of Firefly Luciferase Active Site Amino Acids:  A Proposed Model for Bioluminescence Color. Biochemistry, 38(40), 13223–13230. https://doi.org/10.1021/bi991181o
Branchini, B. R., Magyar, R. A., Murtiashaw, M. H., Anderson, S. M., Helgerson, L. C., & Zimmer, M. (1999b). Site-directed mutagenesis of firefly luciferase active site amino acids: A proposed model for bioluminescence color. Biochemistry, 38(40), 13223–13230.
Branchini, B. R., Magyar, R. A., Murtiashaw, M. H., Anderson, S. M., Helgerson, L. C., & Zimmer, M. (1999c). Site-directed mutagenesis of firefly luciferase active site amino acids: A proposed model for bioluminescence color. Biochemistry, 38(40), 13223–13230.
Branchini, B. R., Magyar, R. A., Murtiashaw, M. H., Anderson, S. M., & Zimmer, M. (1998). Site-directed mutagenesis of histidine 245 in firefly luciferase: A proposed model of the active site. Biochemistry, 37(44), 15311–15319.
Branchini, B. R., Magyar, R. A., Murtiashaw, M. H., Magnasco, N., Hinz, L. K., & Stroh, J. G. (1997). Inactivation of Firefly Luciferase withN-(Iodoacetyl)-N\({'}\)-(5-sulfo-1-naphthyl) ethylenediamine (I-AEDANS). Archives of Biochemistry and Biophysics, 340(1), 52–58.
Branchini, B. R., Magyar, R. A., Murtiashaw, M. H., & Portier, N. C. (2001). The Role of Active Site Residue Arginine 218 in Firefly Luciferase Bioluminescence. Biochemistry, 40(8), 2410–2418. https://doi.org/10.1021/bi002246m
Branchini, B. R., Murtiashaw, M. H., Magyar, R. A., & Anderson, S. M. (2000). The role of lysine 529, a conserved residue of the acyl-adenylate-forming enzyme superfamily, in firefly luciferase. Biochemistry, 39(18), 5433–5440.
Branchini, B. R., Southworth, T. L., DeAngelis, J. P., Roda, A., & Michelini, E. (2006). Luciferase from the Italian firefly Luciola italica: molecular cloning and expression. Comparative Biochemistry and Physiology. Part B, Biochemistry & Molecular Biology, 145(2), 159–167. https://doi.org/10.1016/j.cbpb.2006.06.001
Branchini, B. R., Southworth, T. L., Murtiashaw, M. H., Boije, H., & Fleet, S. E. (2003). A Mutagenesis Study of the Putative Luciferin Binding Site Residues of Firefly Luciferase. Biochemistry, 42(35), 10429–10436. https://doi.org/10.1021/bi030099x
Branchini, B. R., Southworth, T. L., Murtiashaw, M. H., Magyar, R. A., Gonzalez, S. A., Ruggiero, M. C., & Stroh, J. G. (2004). An alternative mechanism of bioluminescence color determination in firefly luciferase. Biochemistry, 43(23), 7255–7262.
Branchini, B. R., Southworth, T. L., Salituro, L. J., Fontaine, D. M., & Oba, Y. (2017). Cloning of the Blue Ghost (Phausis reticulata) Luciferase Reveals a Glowing Source of Green Light. Photochemistry and Photobiology, 93(2), 473–478. https://doi.org/10.1111/php.12649
Cloning, sequence analysis, and expression of active phrixothrix railroad-worms luciferases: Relationship between bioluminescence spectra and primary structures, | biochemistry. (n.d.). https://pubs.acs.org/doi/full/10.1021/bi9900830
Conti, E., Franks, N. P., & Brick, P. (1996). Crystal structure of firefly luciferase throws light on a superfamily of adenylate-forming enzymes. Structure, 4(3), 287–298.
Dementieva, E. I., Fedorchuk, E. A., Brovko, L. Y., Savitskii, A. P., & Ugarova, N. N. (2000). Fluorescent properties of firefly luciferases and their complexes with luciferin. Bioscience Reports, 20(1), 21–30.
Fallon, T. R., Lower, S. E., Chang, C.-H., Bessho-Uehara, M., Martin, G. J., Bewick, A. J., Behringer, M., Debat, H. J., Wong, I., & Day, J. C. (2018). Firefly genomes illuminate parallel origins of bioluminescence in beetles. Elife, 7, e36495.
Franks, N. P., Jenkins, A., Conti, E., Lieb, W. R., & Brick, P. (1998). Structural basis for the inhibition of firefly luciferase by a general anesthetic. Biophysical Journal, 75(5), 2205–2211.
Hall, D. W., Sander, S. E., Pallansch, J. C., & Stanger-Hall, K. F. (2016). The evolution of adult light emission color in North American fireflies. Evolution; International Journal of Organic Evolution, 70(9), 2033–2048. https://doi.org/10.1111/evo.13002
How to set up a Chessboard - A Quick & Simple Guide. (n.d.). https://www.regencychess.co.uk/index.php?main_page=how_to_set_up_a_chessboard.
Kajiyama, N., & Nakano, E. (1991). Isolation and characterization of mutants of firefly luciferase which produce different colors of light. Protein Engineering, 4(6), 691–693. https://doi.org/10.1093/protein/4.6.691
Koksharov, M. I., & Ugarova, N. N. (2008). Random mutagenesis of Luciola mingrelica firefly luciferase. Mutant enzymes with bioluminescence spectra showing low pH sensitivity. Biochemistry. Biokhimiia, 73(8), 862–869. https://doi.org/10.1134/s0006297908080038
Kusy, D., He, J.-W., Bybee, S. M., Motyka, M., Bi, W.-X., Podsiadlowski, L., Li, X.-Y., & Bocak, L. (2021). Phylogenomic relationships of bioluminescent elateroids define the “lampyroid” clade with clicking Sinopyrophoridae as its earliest member. Systematic Entomology, 46(1), 111–123. https://doi.org/10.1111/syen.12451
Lancashire3000. (2022). Mapping from tensor notation to matrix notation, left right or upper lower to row column? [Forum Post]. In Physics Stack Exchange.
Leach, F. R. (2008). A view on the active site of firefly luciferase. Natural Product Communications, 3(9), 1934578X0800300908. https://doi.org/10.1177/1934578X0800300908
Loo, M. P. J. van der. (2014). The stringdist package for approximate string matching. 6, 111–122. https://CRAN.R-project.org/package=stringdist
Martin, G. J., Branham, M. A., Whiting, M. F., & Bybee, S. M. (2017). Total evidence phylogeny and the evolution of adult bioluminescence in fireflies (Coleoptera: Lampyridae). Molecular Phylogenetics and Evolution, 107, 564–575.
Minh, B. Q., Trifinopoulos, J., Schrempf, D., Schmidt, H. A., & Lanfear, R. (2019). IQTREE version 2.0: Tutorials and manual phylogenomic software by maximum likelihood. URL Http://Www. Iqtree. Org.
Morton, R. A., Hopkins, T. A., & Seliger, H. H. (1969). Spectroscopic properties of firefly luciferin and related compounds; an approach to product emission. Biochemistry, 8(4), 1598–1607. https://doi.org/10.1021/bi00832a041
Navizet, I., Liu, Y.-J., Ferré, N., Xiao, H.-Y., Fang, W.-H., & Lindh, R. (2010). Color-Tuning Mechanism of Firefly Investigated by Multi-Configurational Perturbation Method. Journal of the American Chemical Society, 132(2), 706–712. https://doi.org/10.1021/ja908051h
Oba, Y., Konishi, K., Yano, D., Shibata, H., Kato, D., & Shirai, T. (2020). Resurrecting the ancient glow of the fireflies. Science Advances, 6(49), eabc5705. https://doi.org/10.1126/sciadv.abc5705
Oba, Y., Mori, N., Yoshida, M., & Inouye, S. (2010). Identification and characterization of a luciferase isotype in the japanese firefly, luciola cruciata, involving in the dim glow of firefly eggs. Biochemistry, 49(51), 10788–10795. https://doi.org/10.1021/bi1016342
Oba, Y., Yoshida, M., Shintani, T., Furuhashi, M., & Inouye, S. (2012). Firefly luciferase genes from the subfamilies Psilocladinae and Ototretinae (Lampyridae, Coleoptera). Comparative Biochemistry and Physiology. Part B, Biochemistry & Molecular Biology, 161(2), 110–116. https://doi.org/10.1016/j.cbpb.2011.10.001
Ohmiya, Y., Ohba, N., Toh, H., & Tsuji, F. I. (1995). CLONING, EXPRESSION and SEQUENCE ANALYSIS OF cDNA FOR THE LUCIFERASES FROM THE JAPANESE FIREFLIES, Pyrocoelia tniyako AND Hotaria parvula. Photochemistry and Photobiology, 62(2), 309–313. https://doi.org/10.1111/j.1751-1097.1995.tb05273.x
Powell, G. S., Saxton, N. A., Pacheco, Y. M., Stanger-Hall, K. F., Martin, G. J., Kusy, D., Silveira, L. F. L. D., Bocak, L., Branham, M. A., & Bybee, S. M. (2022). Beetle bioluminescence outshines aerial predators (p. 2021.11.22.469605). bioRxiv. https://doi.org/10.1101/2021.11.22.469605
Sandalova, T. P., & Ugarova, N. N. (1999). Model of the active site of firefly luciferase. Biochemistry. Biokhimiia, 64(8), 962–967.
Shane. (2010). Answer to "Elegant way to check for missing packages and install them?". In Stack Overflow.
Shapiro, E., Lu, C., & Baneyx, F. (2005). A set of multicolored Photinus pyralis luciferase mutants for in vivo bioluminescence applications. Protein Engineering, Design and Selection, 18(12), 581–587. https://doi.org/10.1093/protein/gzi066
Sievert, C., Parmer, C., Hocking, T., Chamberlain, S., Ram, K., Corvellec, M., & Despouy, P. (2022). Plotly: Create interactive web graphics via plotly.js. https://CRAN.R-project.org/package=plotly
Tafreshi, N. K., Sadeghizadeh, M., Emamzadeh, R., Ranjbar, B., Naderi-Manesh, H., & Hosseinkhani, S. (2008). Site-directed mutagenesis of firefly luciferase: implication of conserved residue(s) in bioluminescence emission spectra among firefly luciferases. The Biochemical Journal, 412(1), 27–33. https://doi.org/10.1042/BJ20070733
Tatsumi, H., Masuda, T., Kajiyama, N., & Nakano, E. (1989). Luciferase cDNA from Japanese firefly, Luciola cruciata: cloning, structure and expression in Escherichia coli. Journal of Bioluminescence and Chemiluminescence, 3(2), 75–78. https://doi.org/10.1002/bio.1170030208
TrainingPizza. (2021). Answer to "Saving a DataFrame to .txt-file in R (every value in new line)". In Stack Overflow.
Ugarova, N. N., & Brovko, L. Y. (2002). Protein structure and bioluminescent spectra for firefly bioluminescence. Luminescence, 17(5), 321–330. https://doi.org/10.1002/bio.688
Ugarova, N. N., & Sandalova, T. P. (1998). Firefly luciferase: From the structure to the functions. Bioluminescence and Chemiluminescence: Perspective for the 21st Century (Roda A, Pazzagli M, Kricka LJ, Stanley PE Eds) John Wiley and Sons, Chichester, 437–443.
Viviani, V. R., Gabriel, G. V. M., Bevilaqua, V. R., Simões, A. F., Hirano, T., & Lopes-de-Oliveira, P. S. (2018). The proton and metal binding sites responsible for the pH-dependent green-red bioluminescence color tuning in firefly luciferases. Scientific Reports, 8(1), 17594. https://doi.org/10.1038/s41598-018-33252-x
Viviani, V. R., Uchida, A., Viviani, W., & Ohmiya, Y. (2002). The Influence of Ala243 (Gly247), Arg215 and Thr226 (Asn230) on the Bioluminescence Spectra and pH-Sensitivity of Railroad Worm, Click Beetle and Firefly Luciferases. Photochemistry and Photobiology, 76(5), 538–544.
Wang, Y., Akiyama, H., Terakado, K., & Nakatsu, T. (2013). Impact of Site-Directed Mutant Luciferase on Quantitative Green and Orange/Red Emission Intensities in Firefly Bioluminescence. Scientific Reports, 3(1), 2490. https://doi.org/10.1038/srep02490
Warnes, G. R., Bolker, B., Bonebakker, L., Gentleman, R., Huber, W., Liaw, A., Lumley, T., Maechler, M., Magnusson, A., Moeller, S., Schwartz, M., & Venables, B. (2022). Gplots: Various r programming tools for plotting data. https://github.com/talgalili/gplots
Wickham, H., Chang, W., Henry, L., Pedersen, T. L., Takahashi, K., Wilke, C., Woo, K., Yutani, H., & Dunnington, D. (2023). ggplot2: Create elegant data visualisations using the grammar of graphics. https://CRAN.R-project.org/package=ggplot2
Zhao, H., Doyle, T. C., Coquoz, O., Kalish, F., Rice, B. W., & Contag, C. H. (2005). Emission spectra of bioluminescent reporters and interaction with mammalian tissue determine the sensitivity of detection in vivo. Journal of Biomedical Optics, 10(4), 041210. https://doi.org/10.1117/1.2032388
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIHRoZSBFdm9sdXRpb24gb2YgTHVjaWZlcmFzZTEgYW5kIGl0cyBSZWxhdGlvbnNoaXAgdG8gRW1pc3Npb24gU3BlY3RyYSIKYXV0aG9yOiAiQXVkZW4gQmxvY2siCmRhdGU6ICIwNC8xMi8yMDIzIgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIGNvZGVfZm9sZGluZzogaGlkZSAjSGlkZSB0aGUgY29kZSB1bmxlc3MgdXNlcnMgd2lzaCB0byBzZWUuIAogICAgdG9jOiBUUlVFICNUYWJsZSBvZiBDb250ZW50cyAKICAgIHRvY19kZXB0aDogMSAjSG93IG1hbnkgbGV2ZWxzIGFyZSBzaG93biBpbiB0aGUgVE9DCiAgICB0b2NfZmxvYXQ6IFRSVUUgI0Zsb2F0IHRoZSBUT0MgZG93biB0aGUgcmlnaHQgc2l0ZQogICAgY29kZV9kb3dubG9hZDogVFJVRSAjQWxsb3cgdXNlcnMgdG8gZG93bmxvYWQgdGhlIHJhdyBzb3VyY2UgY29kZS4gCiAgem90ZXJvOiB0cnVlICNMaW5rcyBab3Rlcm8gRHJpdmUgdG8gdGhpcyBNYXJrZG93bi4KYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYiAjQ2l0YXRpb25zIHN0b3JhZ2UgZmlsZS4gCmNzbDogYXBhLmNzbCAjY2l0YXRpb24gc3R5bGUKbGluay1jaXRhdGlvbnM6IHllcyAjTGluayBjaXRhdGlvbnMgdG8gdGhlIC5iaWIgZmlsZS4gCm5vY2l0ZTogfAogIEB0cmFpbmluZ3BpenphQW5zd2VyU2F2aW5nRGF0YUZyYW1lMjAyMSwgQHNoYW5lQW5zd2VyRWxlZ2FudFdheTIwMTAsIEBhbW9zMjAxOAogIAplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKSAjS25pdCBmdW5jdGlvbi4KCgojTW9kaWZpZWQgZnJvbSBTaGFuZSwgMjAxMC4KI1RoZSBQYWNrYWdlcyByZXF1aXJlZCBmb3IgdGhpcyBtYXJrZG93bi4KbGlzdC5vZi5wYWNrYWdlcyA8LSBjKCJzdHJpbmdkaXN0IiwgImFiaW5kIiwgInN0cmluZ3IiLCAic3RhdHMiLCAiZHBseXIiLCAicmVzaGFwZTIiLCAicmVhZHhsIiwgInRpZHl2ZXJzZSIsICJncGxvdHMiLCAicGxvdGx5IiwgImdncGxvdDIiLCAiZGljaHJvbWF0IikgCiNDaGVjayBpZiB0aGUgcGFja2FnZXMgZXhpc3QgaW4gdGhlIHVzZXIncyBwYWNrYWdlcyBkaXJlY3RvcnkuCm5ldy5wYWNrYWdlcyA8LSBsaXN0Lm9mLnBhY2thZ2VzWyEobGlzdC5vZi5wYWNrYWdlcyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywiUGFja2FnZSJdKV0gCiNJZiBub3QsIGluc3RhbGwgdGhlbS4KaWYobGVuZ3RoKG5ldy5wYWNrYWdlcykpIGluc3RhbGwucGFja2FnZXMobmV3LnBhY2thZ2VzKQoKI1JlbW92ZSB0aGUgUGFja2FnZSB2ZWN0b3JzLgpybShsaXN0Lm9mLnBhY2thZ2VzLCBuZXcucGFja2FnZXMpCgoKI0FuYWx5c2lzLgogIGxpYnJhcnkoc3RyaW5nZGlzdCkgI01hdHJpeGluZy4gCiAgICAjaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3N0cmluZ2Rpc3Qvc3RyaW5nZGlzdC5wZGYKICBsaWJyYXJ5KGFiaW5kKSAjQmluZGluZyBtYXRyaXggdG8gdGhlIG5leHQgb25lLgogICAgI2h0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9hYmluZC9hYmluZC5wZGYKICBsaWJyYXJ5KHN0cmluZ3IpICMgTXV0YXRpbmcgdGhlIHN0cmluZ3MuCiAgICAjaHR0cHM6Ly9zdHJpbmdyLnRpZHl2ZXJzZS5vcmcKICBsaWJyYXJ5KHN0YXRzKSAjU3RhdCBhbmFseXNpcyAKICAgICNodHRwczovL3N0YXQuZXRoei5jaC9SLW1hbnVhbC9SLWRldmVsL2xpYnJhcnkvc3RhdHMvaHRtbC8wMEluZGV4Lmh0bWwKICBsaWJyYXJ5KGRwbHlyKSAjIE11dGF0aW5nIGRhdGFmcmFtZXMuCiAgICAjaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnCiAgbGlicmFyeShyZXNoYXBlMikgI211dGF0aW5nIGRhdGFmcmFtZXMuCiAgICAjaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3Jlc2hhcGUyL2luZGV4Lmh0bWwKICBsaWJyYXJ5KHJlYWR4bCkgI0FsbG93cyBmb3IgcmVhZGluZyBleGNlbCBmaWxlIGluc3RlYWQgb2YgLmNzdiBmaWxlcy4gCiAgICNodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvcmVhZHhsL3ZlcnNpb25zLzEuNC4yCiAgbGlicmFyeSh0aWR5dmVyc2UpICNFeHBvcnRhdGlvbiBhbmQgZGF0YWZyYW1lIHRvIGZhc3RhIG11dGF0aW9uLiAKICAgI2h0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvCgojUGxvdHRpbmcgCmxpYnJhcnkoZ3Bsb3RzKQojaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dwbG90cy9pbmRleC5odG1sCmxpYnJhcnkocGxvdGx5KQojaHR0cHM6Ly9wbG90bHkuY29tL3IvCmxpYnJhcnkoZ2dwbG90MikKI2h0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnCgojVmlzdWFsaXphdGlvbgpsaWJyYXJ5KGRpY2hyb21hdCkKCmBgYAoKIyMjIEFiYnJldmlhdGlvbiBLZXkKCmBgYHtyIEFiYnJldmlhdGlvbnMsIGVjaG8gPUZBTFNFfQoKYWJiciA8LSByZWFkX2V4Y2VsKCJTdXBwbGVtZW50YXJ5IE1hdGVyaWFscy54bHN4Iiwgc2hlZXQgPSAiQWJicmV2aWF0aW9ucyIpCgoKa25pdHI6OmthYmxlKAogIGFiYnIsCiAgY29sLm5hbWVzID0gZ3N1YigiW19dIiwgIiAiLCBuYW1lcyhhYmJyKSksCiAgY2FwdGlvbiA9ICdUaGUgZnVsbCBuYW1lIGFuZCBhYmJyZXZpYXRpb24gb2YgYWxsIG9yZ2FuaXNtcyB1c2VkIGluIHRoaXMgc3R1ZHkuJwogICkKCgpgYGAKCiMgSW50cm9kdWN0aW9uCgrCoMKgwqDCoMKgQmlvbHVtaW5lc2NlbmNlLCBvciB0aGUgYWJpbGl0eSB0byBwcm9kdWNlIGFuZCBlbWl0IGxpZ2h0IGJ5IGEgbGl2aW5nIG9yZ2FuaXNtLCBpcyB0aG91Z2h0IHRvIGJlIHNoYXJlZCBhY3Jvc3MgZml2ZSBmYW1pbGllcyBvZiBiZWV0bGVzOiBFbGF0ZXJpZGFlLCBMYW1weXJpZGFlLCBQaGVuZ29kaWRhZSwgUmhhcGh0aGFsbWlkYWUsIGFuZCBTaW5vcGh5cm9waG9yaWRhZSBbQHBvd2VsbEJlZXRsZUJpb2x1bWluZXNjZW5jZU91dHNoaW5lczIwMjJdLiBBY3Jvc3MgdGhlc2UgZmFtaWxpZXMsIHJlc2VhcmNoIGhhcyBzaG93biB0aGF0IGl0IGhhcyBlbWVyZ2VkIGluZGVwZW5kZW50bHkgdHdpY2U6IG9uY2UgaW4gY2xpY2sgYmVldGxlcyAoRWxhdGVyaWRhZSkgYW5kIGFub3RoZXIgdGltZSBpbiBhbiBhbmNlc3RvciBvZiB0aGUgbGFtcHlyb2lkIGNsYWRlOiBMYW1weXJpZGFlLCBSaGFnb3BodGFsbWlkYWUsIFNpbm9waHlyb3Bob3JpZGFlLCBhbmQgUGhlbmdvZGlkYWUgW0BmYWxsb25GaXJlZmx5R2Vub21lc0lsbHVtaW5hdGUyMDE4OyBAa3VzeVBoeWxvZ2Vub21pY1JlbGF0aW9uc2hpcHNCaW9sdW1pbmVzY2VudDIwMjE7IEBtYXJ0aW5Ub3RhbEV2aWRlbmNlUGh5bG9nZW55MjAxN10uIEZ1cnRoZXJtb3JlLCBpdCBpcyB0aG91Z2h0IHRvIGJlIHBhcnQgb2YgYSBnZW5lIGR1cGxpY2F0aW9uIGV2ZW50IGF0IGEgY29tbW9uIGFuY2VzdG9yIG9mIHRoZSBMYW15cmlkYWUgbGluZWFnZSwgaW1wbGljYXRpbmcgdGhhdCBhbGwgZmlyZWZsaWVzIGhhdmUgdHdvIGJpb2x1bWluZXNjZW50IGdlbmVzOiBMdWMxIGFuZCBMdWMyIFtcQHJlZihmaWc6RmlndXJlMildLiBIb3dldmVyLCBzbyBmYXIgdGhpcyBMdWMyIGlzb3R5cGUgaGFzIG9ubHkgYmVlbiBpc29sYXRlZCBpbiAqTGwuIGNydWNpYXRlKiBhbmQgKkxsLiBwYXJ2dWxhKiBbQGJlc3Noby11ZWhhcmFJZGVudGlmaWNhdGlvbkNoYXJhY3Rlcml6YXRpb25MdWMydHlwZTIwMTddLiBUaGlzIGR1cGxpY2F0aW9uIGFsbG93ZWQgZm9yIGZpcmVmbGllcyB0byBkZXZlbG9wIHR3byBkaWZmZXJlbnQgcHJvdGVpbnMgdGhhdCBjYW4gYmUgZXhwcmVzc2VkIGZvciBkaWZmZXJlbnQgbmVlZHMuIEl0IGlzIHRob3VnaHQgdGhhdCBMdWMxIGlzIHByZWRvbWluYXRlbHkgZXhwcmVzc2VkIGluIGxhcnZhZSwgcHJlcHVwYWUsIHB1cGFlLCBhbmQgYWR1bHRzLiBEdWUgdG8gdGhlIG1hdGNoIGluIHZpc3VhbCBzZW5zaXRpdml0eSBvZiAqTGwuIHBhcnZ1bGEqIGV5ZXMgdG8gdGhhdCBvZiBMdWMxLCBpdHMgcm9sZSBpcyBiZWxpZXZlZCB0byBiZSBmb3IgaW50cmFzcGVjaWZpYyBjb21tdW5pY2F0aW9uLCB1bmxpa2UgdGhhdCBvZiBMdWMyLiBDdXJyZW50bHksIG9ubHkgYSBmZXcgc3BlY2llcyBoYXZlIGhhZCB0aGUgTHVjMiBnZW5lIGlzb2xhdGVkLCBidXQgaXQgaXMgYmVsaWV2ZWQgdGhhdCB0aGUgZXh0YW50IEx1YzIgaXMgdXNlZCB0byBleHByZXNzIGEgZ3JlZW4gZ2xvdyBpbiB0aGUgZWdncywgcHJlcHVwYWUsIHB1cGFlLCBhbmQgYWR1bHQgZmVtYWxlcyBvZiAqTGwuIGNydWNpYXRlKiBhbmQgKkxsLiBsYXRlcmFsaXMqIFtAYmVzc2hvLXVlaGFyYUlkZW50aWZpY2F0aW9uQ2hhcmFjdGVyaXphdGlvbkx1YzJ0eXBlMjAxN10uCgpgYGB7ciwgRmlndXJlMiwgZmlnLmNhcD0iTW9sZWN1bGFyIHBoeWxvZ2VueSBvZiBsdWNpZmVyYXNlcyBhbmQgcmVsYXRlZCBlbnp5bWVzLiBUaGUgbGVhZiBub2RlcyBhcmUgbGFiZWxlZCB3aXRoIHNwZWNpZXMgbmFtZSwgcHJvdGVpbiBuYW1lLCBhbmQgR2VuQmFuayBhY2Nlc3Npb24gbnVtYmVyLiBCcmFuY2hlcyBhcmUgbGFiZWxlZCB3aXRoIGJvb3RzdHJhcCBwcm9iYWJpbGl0eSAoMTAwMCByZWNvbnN0cnVjdGlvbnMpLiBUaGUgcmVzdXJyZWN0ZWQgYW5jZXN0cmFsIG5vZGVzIGFyZSBzaG93biBhcyBhIHNxdWFyZS4gVGhlIGxlYWYgbm9kZXMgYXJlIGluZGljYXRlZCB3aXRoIGluIHZpdHJvIGx1bWluZXNjZW50IGNvbG9ycyAoZ3JlZW4sIHllbGxvdy1ncmVlbiwgeWVsbG93LCBvcmFuZ2UsIG9yIHJlZCkganVkZ2VkIGJ5IHRoZSBsdW1pbmVzY2VuY2UgbWF4aW11bSB2YWx1ZXM6IEdyZWVuLCBHUiwgNTIwLTU0OSBubTsgWWVsbG93LWdyZWVuLCBZRywgNTUwLTU1OSBubTsgWWVsbG93LCBZRSwgNTYwLTU4NCBubSBbQG9iYVJlc3VycmVjdGluZ0FuY2llbnRHbG93MjAyMF0uIiwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjgwJSIsIGVjaG89RkFMU0V9CgogICAga25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkltYWdlcy9GaWd1cmUyLmpwZWciKQoKYGBgCgrCoMKgwqDCoMKgVG8gcHJvZHVjZSBsaWdodCwgdGhlIGZpcmVmbHkgbHVjaWZlcmluIGlzIGNvbnZlcnRlZCBpbnRvIGFuIGV4Y2l0ZWQgc3RhdGUgb3h5bHVjaWZlcmluIHByb2R1Y3QgKEZpZ3VyZSBcQHJlZihmaWc6bHVjaWZlcmFzZSkpLiBTdXJwcmlzaW5nbHksIGRlc3BpdGUgYWxsIGZpcmVmbGllcyB1c2luZyB0aGUgc2FtZSBsdWNpZmVyaW4gc3Vic3RyYXRlLCB0aGUgd2F2ZWxlbmd0aCBlbWl0dGVkIHZhcmllcyBhY3Jvc3MgdGhlIHBoeWx1bSBbQGJyYW5jaGluaTE5OTldLiBUeXBpY2FsbHksIGZpcmVmbGllcyBlbWl0IGEgcGVhayBlbWlzc2lvbiBzcGVjdHJhIGluIHZpdm8gYmV0d2VlbiA1NDAtNTgwbm0gKGdyZWVuIHRvIHllbGxvdyBsaWdodCkgW0BoYWxsRXZvbHV0aW9uQWR1bHRMaWdodDIwMTY7IEBuYXZpemV0Q29sb3JUdW5pbmdNZWNoYW5pc21GaXJlZmx5MjAxMDsgQHVnYXJvdmFQcm90ZWluU3RydWN0dXJlQmlvbHVtaW5lc2NlbnQyMDAyXS4gVGhpcyBkaWZmZXJlbmNlIGluIGVtaXNzaW9uIGhhcyBhIGNvdXBsZSBvZiBkaWZmZXJlbnQgaHlwb3RoZXNpemVkIHJlYXNvbnMgaW4gZmlyZWZsaWVzLiBUaGUgbW9zdCBwcm9taW5lbnQgZmFjdG9yIHJlc2VhcmNoZXJzIGJlbGlldmUgdG8gYmUgcmVzcG9uc2libGUgaXMgdGhhdCBhbWlubyBhY2lkIHN1YnN0aXR1dGlvbnMgaW4gdGhlIGFjdGl2ZSBzaXRlcyBvZiBMdWNpZmVyYXNlIHByb3RlaW5zIHJlc3VsdHMgaW4gYSBzdWJzdGFudGlhbCBhbHRlcmF0aW9uIHRvIGEgZmlyZWZseSdzIHBlYWsgZW1pc3Npb24gc3BlY3RyYSBbQGJyYW5jaGluaTE5OTk7IEBtb3J0b25TcGVjdHJvc2NvcGljUHJvcGVydGllc0ZpcmVmbHkxOTY5XS4gQWRkaXRpb25hbGx5LCBudW1lcm91cyByZXNlYXJjaGVycyBoYXZlIHNob3duIHRoYXQgc2l0ZSBzcGVjaWZpYyBhbWlubyBhY2lkIGNoYW5nZXMgcmVzdWx0cyBpbiBhIHNoaWZ0IG9mIHRoZSBsdWNpZmVyYXNlIHBlYWsgZW1pc3Npb24gd2F2ZWxlbmd0aCAqaW4gdml0cm8qIFtAYnJhbmNoaW5pUm9sZUFjdGl2ZVNpdGUyMDAxOyBAc2hhcGlyb1NldE11bHRpY29sb3JlZFBob3RpbnVzMjAwNTsgQHdhbmdJbXBhY3RTaXRlRGlyZWN0ZWRNdXRhbnQyMDEzXS4gSG93ZXZlciwgd2hpbGUgdGhlc2Ugc2luZ2xlIHBvaW50IG11dGFnZW5lc2lzIG1vZGVscyBzaG93IHRoYXQgdGhlc2UgY2hhbmdlcyBkbyBpbmZsdWVuY2UgdGhlIGVtaXNzaW9uIHNwZWN0cmEgZW1pdHRlZCBieSBmaXJlZmx5IGJpb2x1bWluZXNjZW5jZSwgZmlyZWZseSBzcGVjaWVzIGhhdmUgYSBzaWduaWZpY2FudCBudW1iZXIgb2YgbXV0YXRpb25zIGFjcm9zcyB0aGUgZW50aXJlIHByb3RlaW4uIEFzIHN1Y2gsIGEgY291cGxlIG9mIGV4cGVjdGVkIG1vZGVscyBjYW4gYmUgZ2VuZXJhdGVkLiBUaGUgZmlyc3QgaXMgdGhhdCB0aGUgZW50aXJlIHByb3RlaW4gY29tcGxleCBtYXR0ZXJzIHdoZW4gZGV0ZXJtaW5pbmcgY29sb3IsIG1lYW5pbmcgdGhlIG1vcmUgYW1pbm8gYWNpZCBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNwZWNpZXMsIHRoZSBncmVhdGVyIHRoZSBkaWZmZXJlbmNlIGluIGFic29sdXRlIGVtaXNzaW9uIHNwZWN0cmEuIE9yLCBhbiBhbHRlcm5hdGl2ZSBjb3VsZCBiZSB0aGF0IGEgZmlyZWZseSdzIGxpZ2h0IGVtaXNzaW9uIGlzIGRlcGVuZGVudCBvbiB0aGUgcHJvdGVpbnMgYXQgc3BlY2lmaWMgc2l0ZXMgd2hlcmUgdGhlIGVuenltZSBhbmQgc3Vic3RyYXRlIGludGVyYWN0IChrbm93biBhcyBhY3RpdmUgc2l0ZXMpLiBJbiB0aGlzIHN5c3RlbSwgaXQgaXNuJ3QgdGhlIHRvdGFsIG51bWJlciBvZiBjaGFuZ2VzLCBidXQgdGhlIGNoYW5nZXMgdGhhdCBvY2N1ciBhdCB0aGVzZSBhY3RpdmUgc2l0ZXMgdGhhdCBpbmZsdWVuY2UgdGhlIGVtaXNzaW9uIGNvbG9yIG9mIGEgZmlyZWZseS4KCmBgYHtyIGx1Y2lmZXJhc2UsIG91dC53aWR0aD0iODAlIiwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJNZWNoYW5pc20gb2YgZmlyZWZseSBsdWNpZmVyYXNlIGNhdGFseXplZCBiaW9sdW1pbmVzY2VuY2UgYW5kIFRJQ1QgZXhjaXRlZCBzdGF0ZSBvZiBveHlsdWNpZmVyaW4gW0BicmFuY2hpbmkxOTk5XS4iLCAsIGVjaG89RkFMU0V9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiSW1hZ2VzL0ZpZ3VyZTEucG5nIikKCmBgYAoKwqDCoMKgwqDCoEluIHRoaXMgcGFwZXIsIEkgYW5hbHl6ZSB0aGUgZXZvbHV0aW9uYXJ5IGhpc3Rvcnkgb2YgTHVjMSB3aXRoaW4gYSBzdWJzZXQgb2Ygc2l4dGVlbiBmaXJlZmx5IHNwZWNpZXMgdG8gZWx1Y2lkYXRlIGEgcG90ZW50aWFsIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHByb3RlaW4gc3RydWN0dXJlIG9mIGVhY2ggc3BlY2llcyBhbmQgdGhlIGFic29sdXRlIGRpZmZlcmVuY2UgaW4gcGVhayBlbWlzc2lvbiBzcGVjdHJhLiBGaXJzdCwgYSBwaHlsb2dlbmV0aWMgdHJlZSB3YXMgZ2VuZXJhdGVkIHRvIGRldGVybWluZSBwb3RlbnRpYWwgcGh5bG9nZW5ldGljIGNvcnJlbGF0aW9uIGJldHdlZW4gc3BlY2llcyBvZiBpbnRlcmVzdCBhbmQgdGhlIHdhdmVsZW5ndGggZW1pdHRlZC4gTmV4dCwgdGhlIGZpcmVmbHkgcHJvdGVpbnMgd2VyZSBhbmFseXplZCBwYWlyd2lzZSB0byBkZXRlcm1pbmUgaWYgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGluIHBlYWsgZW1pc3Npb24gc3BlY3RyYSBhbmQgdGhlIGRpZmZlcmVuY2VzIGluIHRocmVlIGRpZmZlcmVudCBncm91cHM6IGFsbCBhbWlubyBhY2lkcywgbm9uLWFjdGl2ZSBzaXRlcywgYW5kIG9ubHkgYWN0aXZlIHNpdGVzLiBJIGZvdW5kIHRoYXQgdGhlcmUgaXMgbm8gZXZvbHV0aW9uYXJ5IGNvcnJlbGF0aW9uIGFuZCBsaXR0bGUsIGlmIGFueSwgcGFpcndpc2UgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVzZSBncm91cHMgYW5kIHRoYXQgdGhlIHBlYWsgZW1pc3Npb24gc3BlY3RyYSBvZiBhIGZpcmVmbHkgaXMgbGlrZWx5IGRldGVybWluZWQgYnkgYSBtdWx0aXR1ZGUgb2YgZmFjdG9ycywgbm90IGp1c3QgdGhlIHByb3RlaW4gc3RydWN0dXJlLgoKIyBNZXRob2RzCgojIyBQaHlsb2dlbmV0aWNzCgrCoMKgwqDCoMKgRHVlIHRvIHRoZSByZWR1bmRhbmN5IG9mIGdlbmV0aWMgY29kZSwgdGhlcmUgYXJlIGRpZmZlcmVudCBldm9sdXRpb25hcnkgcHJlc3N1cmVzIHBsYWNlZCBvbiBkaWZmZXJlbnQgY29kb24gcG9zaXRpb25zLiBTaW5jZSB0aGUgdGhpcmQgY29kb24gaXMgdGhlIGxlYXN0IGZ1bmN0aW9uYWxseSBjb25zdHJhaW5lZCwgbXV0YXRpb25zIGFyZSBtb3JlIGxpa2VseSB0byBvY2N1ciB0aGVyZSBhbmQgYmUgcGFzc2VkIHRvIHRoZSBuZXh0IGdlbmVyYXRpb24gW0Bib2ZraW5WYXJpYXRpb25Fdm9sdXRpb25hcnlQcm9jZXNzZXMyMDA3XS4gVGhpcyBiZWNvbWVzIGEgcHJvYmxlbSB3aGVuIGF0dGVtcHRpbmcgdG8gY3JlYXRlIGEgcGh5bG9nZW55IG9mIHBhaXJ3aXNlIGRpc3RhbmNlcywgYXMgdGhlc2UgbXV0YXRpb25zIGNvdWxkIGJlIGNhc2VzIG9mIGNvbnZlcmdlbnQgZXZvbHV0aW9uLCBjYXVzaW5nIGltcHJvcGVyIGNsdXN0ZXJpbmcuIEFzIHN1Y2gsIHNpeHRlZW4ga25vd24gTHVjMSBwcm90ZWluIHNlcXVlbmNlcyAoVGFibGUgXEByZWYodGFiOlNwZWNpZXMpOyBTdXBwbGVtZW50YXJ5IFRhYmxlIFxAcmVmKHRhYjpTVDEpKSwgd2VyZSBpbXBvcnRlZCBpbnRvIEdlbmVpb3VzIFByaW1lIHRvIGhhdmUgdGhlICpPKnBlbiAqUiplYWRpbmcgKkYqcmFtZSAoT1JGKSBleHRyYWN0ZWQgKGZvciBleHBsaWNpdCBzdGVwcyBzZWUgXEByZWYoZ2VuZWlvdXMtcHJpbWUtb3JmLWV4dHJhY3Rpb24pKS4KCmBgYHtyIFNwZWNpZXMsIGVjaG89RkFMU0V9CgpTVDEgPC0gcmVhZF9leGNlbCgiU3VwcGxlbWVudGFyeSBNYXRlcmlhbHMueGxzeCIsIHNoZWV0ID0gIlNUMSIpCgpzcGVjaWVzIDwtIHNlbGVjdChTVDEsIFNwZWNpZXMsIEdlbkJhbmtfTm8uLCBsbWF4X25tLCBgQ29sb3VyYXRpb24qYCkKCmtuaXRyOjprYWJsZSgKICBzcGVjaWVzLAogIGNvbC5uYW1lcyA9IGdzdWIoIltfXSIsICIgIiwgbmFtZXMoc3BlY2llcykpLAogIGNhcHRpb24gPSAnT3JnYW5pc21zIFN0dWRpZWQgYW5kIHN1cHBsZW1lbnRhcnkgZGF0YSBhYm91dCBlYWNoLiAqR3JlZW4sIEdSLCA1MjAtNTQ5IG5tOyBZZWxsb3ctZ3JlZW4sIFlHLCA1NTAtNTU5IG5tOyBZZWxsb3csIFlFLCA1NjAtNTg0IG5tLiAoTW9kaWZpZWQgZnJvbTogQG9iYVJlc3VycmVjdGluZ0FuY2llbnRHbG93MjAyMCknCiAgKQoKCmBgYAoKwqDCoMKgwqDCoE5leHQsIHRoZXNlIE9SRnMgYXJlIGJyb3VnaHQgaW50byBSIHRvIGhhdmUgdGhlIGZpcnN0IGFuZCBzZWNvbmQgY29kb24gcG9zaXRpb24gcmVtb3ZlZCwgbGVhdmluZyBvbmx5IHRoZSB0aGlyZCBjb2RvbiB0byBiZSBhbmFseXplZC4KCmBgYHtyIFRoaXJkQ29kb25FeHRyYWN0aW9uLCBlY2hvPSBUUlVFLCByZXN1bHRzPSdoaWRlJywgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdyd9CgojSW1wb3J0IFRhYmxlLgogIE9SRnMgPC0gcmVhZC50YWJsZSgiUGh5bG9nZW5ldGljcy9PUkZzLnR4dCIsIHNlcD0iLCIsIGhlYWRlcj1GQUxTRSkKI0JsYW5rIFZlY3RvciBvZiB0aGUgZmluYWwgbnVjbGVvdGlkZXMuCiAgb25seS50aGlyZCA8LSBjKCkgCgojVGhpcmQgQ29kb24gUmVtb3ZhbC4KZm9yIChzcGVjaWVzIGluIE9SRnMkVjIpIHsgCiAgI1NwbGl0IHRoZSBudWNsZW90aWRlcyBpbnRvIHNpbmdsZSBsZXR0ZXIgc3RyaW5ncy4gCiAgICBzcGxpdCA8LSBzdHJzcGxpdChzcGVjaWVzLHNwbGl0ID0gIiIpCiAgI0V4dHJhY3QgdGhlIHRoaXJkIGNvZG9uLiAKICAgIGV4dHJhY3RlZCA8LSBzdHJfcmVtb3ZlX2FsbCh0b1N0cmluZyhzcGxpdFtbMV1dW3NlcSgzLCBsZW5ndGgoc3BsaXRbWzFdXSksIDMpXSksICIsICIpCiAgI09yZGVyIG9mIE9wZXJhdGlvbnM6CiAgICAjY3JlYXRlIGEgc3RyaW5nIGNvdW50aW5nIGV2ZXJ5IHRoaXJkIHBvc2l0aW9uIGludG8gYSBuZXcgdmVjdG9yLCByZW1vdmUgdGhvc2UgaW5kZXhlcyBpbnRvIGEgbmV3IHZlY3Rvci4KICAgICNBZGQgdGhlIHN0cmluZyBhcyBhIG5ldyBpbmRleC4KICAgIG9ubHkudGhpcmQgPC0gYyhvbmx5LnRoaXJkLCBleHRyYWN0ZWQpIAogIAp9CiNSZW1vdmUgdGhlIGludGVybWVkaWF0ZSB2ZWN0b3JzIG1hZGUgaW4gZm9yLWxvb3AuCnJtKHNwbGl0LCBleHRyYWN0ZWQsIHNwZWNpZXMpCgojRGF0YWZyYW1lIG9mIHRoZSBzcGVjaWVzIG5hbWUgYW5kIHRoZSB0aGlyZCBjb2Rvbi1vbmx5IGZpbGVzLiAKdGhpcmQuY29kb25zLmRmIDwtIGRhdGEuZnJhbWUoT1JGcyRWMSwgb25seS50aGlyZCkKCgojTW9kaWZpZWQgZnJvbTogVHJhaW5pbmdQaXp6YSwgMjAyMQogICNDcmVhdGUgYSB2ZWN0b3IgdGhhdCBjYW4gYmUgZXhwb3J0ZWQgYXMgYSAuZmFzdGEKICB0aGlyZF9jb2RvbnNfcHJpbnQgPC0gCiAgICB0aGlyZC5jb2RvbnMuZGYgJT4lIAogICAgcm93d2lzZSgpICU+JQogICAgcGl2b3RfbG9uZ2VyKE9SRnMuVjE6b25seS50aGlyZCkgJT4lCiAgICBzZWxlY3QoLW5hbWUpCiAgCiAgI0V4cG9ydCB0aGUgZGF0YWZyYW1lIGFzIGEgLmZhc3RhLgogIHdyaXRlLnRhYmxlKHRoaXJkX2NvZG9uc19wcmludCwKICAgICAgICAgICAgICBmaWxlID0gIlBoeWxvZ2VuZXRpY3MvVGhpcmRjb2RvbnNfb25seS5mYXN0YSIsCiAgICAgICAgICAgICAgY29sLm5hbWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgcm93Lm5hbWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgcXVvdGUgPSBGQUxTRSkKYGBgCgrCoMKgwqDCoMKgVGhlc2UgdGhpcmQgY29kb24tb25seSBzZXF1ZW5jZXMgd2VyZSBpbXBvcnRlZCBpbnRvIEJpc29uTmV0IHRvIGNvbnN0cnVjdCBhIHBoeWxvZ2VuZXRpYyB0cmVlLiBXaXRoaW4gdGhlIHByb2dyYW0gSVEtVHJlZSwgTW9kZWxGaW5kZXIgUGx1cyB3YXMgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGJlc3Qgc3Vic3RpdHV0aW9uIG1vZGVsIHRoYXQgZml0cyB0aGUgbnVjbGVvdGlkZSBzZXF1ZW5jZXMgdXNpbmcgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbiAoQUlDKSwgcmVtb3ZpbmcgdGhlIHBvdGVudGlhbCBmb3IgY29udmVyZ2VudCBldm9sdXRpb24gdG8gaW5mbHVlbmNlIHRoZSBwaHlsb2dlbnkgW0BtaW5oSVFUUkVFVmVyc2lvblR1dG9yaWFsczIwMTldLiBUaGUgY2hvc2VuIG1vZGVsIGlzIHRoZW4gdXNlZCB0byBhc3NlbWJsZSBhIHRyZWUgd2l0aGluIElRLXRyZWUuIFRoZSBvdXRncm91cCwgKlBoci4gaGlydHVzKiAoQWNjZXNzaW9uIEFGMTM5NjQ1KSwgd2FzIHNlbGVjdGVkIGFzIGl0cyBsdWNpZmVyYXNlIHByb3RlaW4gaXMga25vd24gdG8gYmUgZGVyaXZlZCBmcm9tIHRoZSBzYW1lIGFuY2VzdHJhbCBsdWNpZmVyYXNlIGFzIExhbXB5cmlkYWUgW0BvYmFSZXN1cnJlY3RpbmdBbmNpZW50R2xvdzIwMjBdLiBUaGUgLnRyZWVmaWxlIHdhcyB0aGVuIGltcG9ydGVkIGludG8gR2VuZWlvdXMgUHJpbWUgYW5kIG1hbnVhbGx5IGNvbG9yLWNvZGVkLgoKYGBge3IgSVEtVFJFRSwgZXZhbD1GQUxTRSwgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdyd9CgojIS9iaW4vYmFzaAojU0JBVENIIC1wIHNob3J0ICMgcGFydGl0aW9uIChxdWV1ZSkKI1NCQVRDSCAtTiAxICMgKGxlYXZlIGF0IDEgdW5sZXNzIHVzaW5nIG11bHRpLW5vZGUgc3BlY2lmaWMgY29kZSkKI1NCQVRDSCAtbiA4ICMgbnVtYmVyIG9mIGNvcmVzCiNTQkFUQ0ggLS1tZW0tcGVyLWNwdT0zMkcgIyBtZW1vcnkgcGVyIGNvcmUKI1NCQVRDSCAtLWpvYi1uYW1lPSJJUXRyZWUiICMgam9iIG5hbWUKI1NCQVRDSCAtbyBzbHVybS4lTi4lai5zdGRvdXQudHh0ICMgU1RET1VUCiNTQkFUQ0ggLWUgc2x1cm0uJU4uJWouc3RkZXJyLnR4dCAjIFNUREVSUgojU0JBVENIIC0tbWFpbC11c2VyPV9fX19fICMgYWRkcmVzcyB0byBlbWFpbAojU0JBVENIIC0tbWFpbC10eXBlPUFMTCAjIG1haWwgZXZlbnRzIChOT05FLCBCRUdJTiwgRU5ELCBGQUlMLCBBTEwpCiNTQkFUQ0ggLS1leGNsdWRlPWhwYy00LGhwYy01LGhwYy02CgoKI0xvYWQgbW9kdWxlOgptb2R1bGUgbG9hZCBwaHlsb2dlbnkKCgojVmFyaWFibGVzOgpiYXJjb2RlPS9ob21lL2FyYjAyNy9DQVBTVE9ORS9UaGlyZENvZG9uX2FsaWdubWVudC5mYXN0YSAjVGhlIGlucHV0IGZpbGUuCm1lcml0PUFJQyAjQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlhIE1ldHJpYyBmb3IgSVEtVHJlZSBNb2RlbEZpbmRlciBQbHVzLgpvdXRncm91cD1SRV9QaHJfaGlydHVzX0FGMTM5NjQ1XzIgI1NlcXVlbmNlIElkZW50aWZpZXIgb2YgdGhlIG91dGdyb3VwLgpib290c3RyYXA9MTAwMDAgI051bWJlciBvZiBib290c3RyYXBzLiAKCiNQcmludCB2YXJpYWJsZXMgdG8gY29uc29sZSAoZm9yIHVzZXIgcmVmZXJlbmNlcyk6CmNhdCA8PE9QVElPTlMKQWxpZ25tZW50IGZpbGU6ICRiYXJjb2RlClNlYXJjaCBmb3IgdGhlIGJlc3QgbW9kZWwgb2Ygc2VxdWVuY2UgZXZvbHV0aW9uIHVzaW5nOiAkbWVyaXQKT3V0Z3JvdXA6ICRvdXRncm91cApOdW1iZXIgb2YgQm9vdHN0cmFwczogJGJvb3RzdHJhcApPUFRJT05TCgojSVF0cmVlOgogICAgI0RvY3VtZW50YXRpb246IGh0dHA6Ly93d3cuaXF0cmVlLm9yZy9kb2MvQ29tbWFuZC1SZWZlcmVuY2UKaXF0cmVlIC1zICRiYXJjb2RlIC1tZXJpdCAkbWVyaXQgLW8gJG91dGdyb3VwICAtYmIgJGJvb3RzdHJhcAoKI1VubG9hZCBtb2R1bGU6Cm1vZHVsZSB1bmxvYWQgcGhsb2dlbnkgCmBgYAoKIyMgUiBBbmFseXNpcwoKwqDCoMKgwqDCoFRoZSBvcmlnaW5hbCBudWNsZW90aWRlIE9SRnMgZm9yIHRoZSBmaXJlZmx5IHByb3RlaW5zICh3ZXJlIHRyYW5zbGF0ZWQgaW50byBwcm90ZWluIHNlcXVlbmNlcyBhbmQgYWxpZ25lZCB1c2luZyBNVVNDTEUgKGFsZ29yaXRobSBQUFAsIEhNTSBQZXJ0dWJhdGlvbnMgPSAwLCBHdWlkZSBUcmVlIFB1cm11dGF0aW9ucyA9IDApIGluIEdlbmVpb3VzIFByaW1lIHRvIGJlIGltcG9ydGVkIGludG8gUi4gV2hpbGUgMTcgTHVjMSBwcm90ZWlucyBoYXZlIHByZXZpb3VzbHkgYmVlbiBpZGVudGlmaWVkIGJ5IEBvYmFSZXN1cnJlY3RpbmdBbmNpZW50R2xvdzIwMjAgYW5kIHdlcmUgdXNlZCB0byBjb25zdHJ1Y3QgdGhlIHBoeWxvZ2VuZXRpYyB0cmVlLCB0aGUgKlB0LiBweXJhbGlzKiBMdWMxIG1STkEgKEFjY2Vzc2lvbjogTTE1MDc3KSBvbmx5IGhhcyAxODIgYW1pbm8gYWNpZHMsIHdoaWxlIHRoZSBvdGhlciBwcm90ZWlucyBoYXZlIGFyb3VuZCA1NjAgcHJvdGVpbnMuIEFkZGl0aW9uYWxseSwgbGF0ZXIgYW5hbHlzaXMgbG9va3MgaW50byBrbm93biBhY3RpdmUgc2l0ZXMgb2YgdGhlIEx1YzEgcHJvdGVpbiB1c2luZyBkYXRhIGZyb20gKlB0LiBQeXJhbGlzKiwgd2hlcmUgdGhlIGZpcnN0IGtub3duIGFjdGl2ZSBzaXRlIGlzIGF0IEFBIHBvc2l0aW9uIDE5Ny4gRXZlbiB3aGVuIGFsaWduZWQgd2l0aCBNVVNDTEUsIGEgc2lnbmlmaWNhbnQgbWFqb3JpdHkgb2YgdGhlIG91dGxpbmVkIGFjdGl2ZSBzaXRlcyBhcmUgbm90IGFsaWduZWQgd2l0aCB0aGUgb3RoZXIgcHJvdGVpbnMgKFN1cHBsZW1lbnRhcnkgRmlndXJlIFxAcmVmKGZpZzpTVEYyKS4gRnVydGhlciByZXNlYXJjaCBpbnRvIHRoaXMgbVJOQSBwcm90ZWluIHdvdWxkIGJlIHJlcXVpcmVkIHRvIGRldGVybWluZSB3aGVyZSB0aGUgYWN0aXZlIHNpdGVzIGFyZSBsb2NhdGVkIHdpdGhpbiB0aGlzIHNwZWNpZmljIHByb3RlaW4uIEhvd2V2ZXIsIHRoZXJlIGlzIGFub3RoZXIga25vd24gbHVjMSBtUk5BIHByb3RlaW4gZm9yIFB0LiBweXJhbGlzIChBY2Nlc3Npb246IEFCNjQ0MjI4KSB0aGF0IGRvZXMgcHJvcGVybHkgYWxpZ24gdG8gb3RoZXIgcHJvdGVpbnMgKFN1cHBsZW1lbnRhcnkgTWF0ZXJpYWxzIFxAcmVmKGZpZzpTVEYyKSkuIEJ5IGxvb2tpbmcgYWNyb3NzIHRoZSBwcmV2aW91c2x5IG91dGxpbmVkIGNhdGVnb3JpZXMgaW4gU3VwcGxlbWVudGFyeSBGaWd1cmUgXEByZWYodGFiOlNUMSkgKEdyZWVuLCBHUiwgNTIwLTU0OSBubTsgWWVsbG93LWdyZWVuLCBZRywgNTUwLTU1OSBubTsgWWVsbG93LCBZRSwgNTYwLTU4NCBubSksIHRoZXNlIHByb3RlaW5zLCBhbG9uZyB3aXRoIHRoZSBlbWlzc2lvbiBzcGVjdHJhIG9mIGVhY2ggc3BlY2llcyBhdCBhIHBIIG9mIDcuOCwgd2VyZSB0aGVuIGFuYWx5emVkIHRvIGRldGVybWluZSB0aGUgYWJzb2x1dGUgcGFpcndpc2UgZGlzdGFuY2UgYmV0d2VlbiBlYWNoIHNwZWNpZXMnIGVtaXNzaW9uIHNwZWN0cmEuCgpgYGB7ciBHbG9iYWxWYXJzLCBlY2hvPUZBTFNFLCBjbGFzcy5zb3VyY2UgPSAnZm9sZC1zaG93J30KCiNDcmVhdGUgdmVjdG9yIGZyb20gdGhlIGFsaWduZWQgY29sdW1uIG9mIHRoZSBtYXN0ZXIgU3VwcGxlbWVudGFyeSBNYXRlcmlhbHMgZXhjZWwgZmlsZS4gCiAgcHJvdGVpbnMgPC0gcmVhZF9leGNlbCgiU3VwcGxlbWVudGFyeSBNYXRlcmlhbHMueGxzeCIsIHNoZWV0ID0gIlByb3RlaW5zIikjREYgb2YganVzdCB0aGUgc3BlY2llcyBuYW1lIGFuZCBwZWFrIGVtaXNzaW9uLiAKICBlbWlzc2lvbiA8LSBzZWxlY3QocHJvdGVpbnMsIE5hbWUsIExtYXgpIAoKCiNNb2RpZmllZCBmcm9tIChBbW9zLCAyMDE4KQogIGRpZmZtYXQgPSBmdW5jdGlvbih4KXsKICAgICNDb2x1bW4vdmVjdG9yIHRvIGJsYW5rIG1hdHJpeCB3aXRoIGRpbWVuc2lvbnMgYXMgdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSBpbnB1dC4gCiAgICBEID0gbWF0cml4KGFzLm51bWVyaWMoTkEpLCBOUk9XKHgpLCBOUk9XKHgpKSAKICAgICNEaWZmZXJlbmNlIGJldHdlZW4gZWFjaCBzaXRlLgogICAgICBmb3IgKGkgaW4gMTpOUk9XKHgpKXsKICAgICAgZCA9IHhbW2ldXSAtIHhbLWldCiAgICAgIERbaSwtaV0gPSBkCiAgICB9CiAgICAjQ2hlY2tpbmcgdGhlIG1hdHJpeCB3YXMgY3JlYXRlZCBjb3JyZWN0bHkuIAogICAgICBpZiAoIWFsbChpcy5uYShkaWFnKEQpKSkpewogICAgICAgIHN0b3AoIk5vdCBhbGwgZGlhZ29uYWwgZWxlbWVudHMgemVybyIpCiAgICAgIH0KICAgICAgZGlhZyhEKSA9IDAKICAgICAgaWYgKCFpcy5udWxsKG5hbWVzKHgpKSkgY29sbmFtZXMoRCkgPSByb3duYW1lcyhEKSA9IG5hbWVzKHgpCiAgICAgIHJldHVybihEKQogIH0KICAgICAgICAgICAgCiNDcmVhdGUgYW4gYWJzb2x1dGUgZGlmZiBpbiBlbWlzc2lvbiBtYXRyaXggdXNpbmcgZnVuY3Rpb24gYWJvdmUuIAogIGFicy5kaWZmLmVtaXNzaW9uLm1hdHJpeCA8LSBhYnMoZGlmZm1hdChlbWlzc2lvbiRMbWF4KSkKCiNOYW1lcwogIGNvbG5hbWVzKGFicy5kaWZmLmVtaXNzaW9uLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQogIHJvd25hbWVzKGFicy5kaWZmLmVtaXNzaW9uLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQoKI01hdHJpeCAtPiBkYXRhZnJhbWUKICBhYnMuZW1pc3Npb24uZGlmZi5kZiA8LSBtZWx0KGFicy5kaWZmLmVtaXNzaW9uLm1hdHJpeCwgdmFybmFtZXMgPSBjKCJTcGVjaWVzMSIsICJTcGVjaWVzMiIpKQogIGNvbG5hbWVzKGFicy5lbWlzc2lvbi5kaWZmLmRmKVszXSA8LSAiYWJzLmVtaXNzaW9uLmRpZmYiICNOYW1lIHRoZSBuZXcgY29sdW1uLgoKCiNDcmVhdGUgdGhlIG1hc3RlciBkYXRhZnJhbWUgZnJvbSB3aGljaCBvdGhlciBjb2RlIGNodW5rcyBhcmUgYWRkZWQgdG8uIAogIGNvbWJpbmVkLmRmIDwtIGFicy5lbWlzc2lvbi5kaWZmLmRmCgpgYGAKCsKgwqDCoMKgwqBUbyBkZXRlcm1pbmUgdGhlIHRvdGFsIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMsIHRoZSBwYWNrYWdlIHN0cmluZ2Rpc3Qgd2FzIHVzZWQgdG8gY3JlYXRlIGEgcGFpcndpc2UgZGlzdGFuY2UgbWF0cml4IGF0IGVhY2ggYW1pbm8gYWNpZCBzaXRlIHVzaW5nIHRoZSBIYW1taW5nIERpc3RhbmNlIE1ldHJpYzogImNvdW50IHRoZSBudW1iZXIgb2YgY2hhcmFjdGVyIHN1YnN0aXR1dGlvbnMgdGhhdCB0dXJucyBiIGludG8gYSwgaWYgYSBhbmQgYiBoYXZlIGRpZmZlcmVudCBudW1iZXIgb2YgY2hhcmFjdGVycyB0aGUgZGlzdGFuY2UgaXMgSW5mIiBbQHN0cmluZ2Rpc3RdLiBGb3IgdGhvc2UgY3VyaW91cyB0b3dhcmRzIHRoZSBhbmFseXNpcyBwcm90b2NvbCB1c2VkLCBzZWUgXEByZWYocGFpcndpc2UtZGlzdGFuY2UtbWF0cml4KS4KCmBgYHtyIEFsbCBBbWlubyBhY2lkIHNpdGVzLCBlY2hvID0gVFJVRSwgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdyd9CgogIGFsaWduLnZlY3RvciA8LSBhcy52ZWN0b3IocHJvdGVpbnMkYWxpZ25lZCkKI0RldGVybWluZSB0aGUgdG90YWwgbGVuZ3RoIG9mIHRoZSBhbGlnbmVkIHByb3RlaW5zIHZlY3Rvci4KICBzaXRlcyA8LSBuY2hhcihhbGlnbi52ZWN0b3JbMV0pCiAgCiAgCiAgCiNNYXRyaXggb2YgYWxsIGFtaW5vIGFjaWQgc2l0ZXMKICBzdW0uYWxsLm1hdHJpeCA8LSBhcy5tYXRyaXgoc3RyaW5nZGlzdG1hdHJpeChhbGlnbi52ZWN0b3IsIG1ldGhvZCA9ICJoYW1taW5nIikpCgojTmFtZXMuIApjb2xuYW1lcyhzdW0uYWxsLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQpyb3duYW1lcyhzdW0uYWxsLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQoKI01hdHJpeCB0byBkZi4Kc3VtLmFsbC5kZiA8LSBtZWx0KHN1bS5hbGwubWF0cml4LCB2YXJuYW1lcyA9IGMoIlNwZWNpZXMxIiwgIlNwZWNpZXMyIikpCiNOYW1lIENvbHVtbi4gCmNvbG5hbWVzKHN1bS5hbGwuZGYpWzNdIDwtICJBbGxEaWZmIgoKI01lcmdlIGludG8gdGhlIG1hc3RlciBkYXRhZnJhbWUuIApjb21iaW5lZC5kZiA8LSBtZXJnZShjb21iaW5lZC5kZiwgc3VtLmFsbC5kZikKCmBgYAoKwqDCoMKgwqDCoEEgc2ltaWxhciBtZXRob2Qgd2FzIGVtcGxveWVkIGZvciBib3RoIGNhbGN1bGF0aW5nIHRoZSBudW1iZXIgb2YgZGlmZmVyZW5jZXMgZXhjbHVkaW5nIHRoZSBhbWlubyBhY2lkIGFjdGl2ZSBzaXRlcyBhbmQgYSBzZXBhcmF0ZSAzLUQgbWF0cml4IGZvciBvbmx5IHRoZSBhY3RpdmUgc2l0ZXMuIFRoZSBhY3RpdmUgc2l0ZXMgZm9yICpQdC4gUHlyYWxpcyogaGF2ZSBwcmV2aW91c2x5IGJlZW4gaWRlbnRpZmllZCBieSBAbGVhY2hWaWV3QWN0aXZlU2l0ZTIwMDggW1RhYmxlIFxAcmVmKHRhYjpTVDIpXS4gRHVyaW5nIGFsaWdubWVudCwgdGVuIHNpdGVzIHdlcmUgYWRkZWQgdG8gdGhlICpQdC4gUHlyYWxpcyogcHJvdGVpbiAoU3VwcGxlbWVudGFyeSBGaWd1cmUgXEByZWYoZmlnOlNURjIpKSwgc28gdGhlc2UgYWN0aXZlIHNpdGVzIHdlcmUgbXV0YXRlZCBieSB0ZW4gZm9yIGFuYWx5c2lzLgoKYGBge3IgSW1wb3J0YXRpb24sIGVjaG89VFJVRSwgcmVzdWx0cz0naGlkZScsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLXNob3cnfQoKI0FjdGl2ZSBzaXRlIFRhYmxlCiAgYWN0aXZlc2l0ZXMudGFibGUgPC0gcmVhZF9leGNlbCgiU3VwcGxlbWVudGFyeSBNYXRlcmlhbHMueGxzeCIsIHNoZWV0ID0gIlNUMiIsICkKI1RhYmxlIHRvIHZlY3RvciBpbmNsdWRpbmcgYWRqdXN0aW5nIGZvciBhbGlnbm1lbnQgKCsxMCkuCiAgYWN0aXZlc2l0ZXMgPC0gYWN0aXZlc2l0ZXMudGFibGUkU2l0ZSArIDEwIAoKYGBgCgrCoMKgwqDCoMKgVG8gYW5hbHl6ZSB0aGUgbnVtYmVyIG9mIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgZXhjbHVkaW5nIHRoZSBhY3RpdmUgc2l0ZXMsIGEgbW9kaWZpZWQgdmVyc2lvbiBvZiBzdHJpbmdkaXN0bWF0cml4IHdhcyB1c2VkIHRvIGNyZWF0ZSBhIHZlY3RvciBvZiBhbGwgNTIyIGFtaW5vIGFjaWRzIHRoYXQgYXJlIG5vdCBrbm93biBhY3RpdmUgc2l0ZXMuIEZvciBlYWNoIGluZGV4IG9mIHRoZSB2ZWN0b3IsIGEgcGFpcndpc2UgZGlzdGFuY2Ugd2FzIHRoZW4gY2FsY3VsYXRlZCwgZ2l2aW5nIGEgbWF0cml4IG9mIDBzIGFuZCAxcywgd2hlcmUgMCBpbmRpY2F0ZXMgbm8gZGlmZmVyZW5jZSBhbmQgMSBlcXVhbHMgYSBkaWZmZXJlbmNlIGF0IHRoZSBzcGVjaWZpYyBzaXRlLiBBcyBlYWNoIHNpdGUgd2FzIGNhbGN1bGF0ZWQsIGl0IHdhcyBtdXRhdGVkIHRvIGEgdGhyZWUgZGltZW5zaW9uYWwgbWF0cml4IGFsb25nIHRoZSB6LWF4aXMsIGdpdmluZyBhIDE1eDE1eDUyMSBtYXRyaXguIFRoaXMgbWF0cml4IHdhcyB0aGVuIHN1bW1lZCBkb3duIHRoZSB6IGF4aXMgdG8gZ2l2ZSB0aGUgdG90YWwgbnVtYmVyIG9mIGRpZmZlcmVuY2VzIGJldHdlZW4gZWFjaCBzcGVjaWVzIGx1Y2lmZXJhc2UgcHJvdGVpbiAoU2VlIFxAcmVmKHZpc3VhbGl6YXRpb24pIGZvciBhIGRldGFpbGVkIGJyZWFrZG93biBvZiBtYXRyaXggZGltZW5zaW9uYWxpdHkgd2l0aCB2aXN1YWxpemF0aW9uKS4KCmBgYHtyIE5vQWN0aXZlU2l0ZXMsIGVjaG89VFJVRSwgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdyd9CiNHZXQgYSB2ZWN0b3Igb2YgdGhlIHRvdGFsIG51bWJlciBvZiBhbWlubyBhY2lkIHNpdGVzLiAKICBzaXRlcyA8LSBjKDE6bmNoYXIoYWxpZ24udmVjdG9yWzFdKSkKCiMgQ3JlYXRlIHRoZSBmaXJzdCBwYWlyd2lzZSBtYXRyaXguIAogIGFsbC5EaXN0bWF0cml4MSA8LSBhcy5tYXRyaXgoc3RyaW5nZGlzdG1hdHJpeChzdHJfc3ViKGFsaWduLnZlY3RvciwgMSwgMSksIG1ldGhvZCA9ICJoYW1taW5nIikpIAogICNPcmRlciBvZiBPcGVyYXRpb25zOgogICNzdHJfc3ViOiBDcmVhdGUgYSB2ZWN0b3Igb2YgdGhlIHByb3RlaW4gYXQgdGhlIGZpcnN0IGFjdGl2ZSBzaXRlLiAKICAjc3RyaW5nZGlzdG1hdHJpeDogRG9lcyBhIHNpbXBsZSBjb21wYXJpc29uIG1hdHJpeCBiZXR3ZWVuIGVhY2ggZ3JvdXAgKDAgPSBpZGVudGljYWwsIDEgPSBkaWZmZXJlbmNlKSB1c2luZyBIYW1taW5nIG1ldGhvZG9sb2d5IChjb3VudHMgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXIgc3Vic3RpdHV0aW9ucyB0aGF0IHR1cm5zIGIgaW50byBhLiBJZiBhIGFuZCBiIGhhdmUgZGlmZmVyZW50IG51bWJlciBvZiBjaGFyYWN0ZXJzIHRoZSBkaXN0YW5jZSBpcyBJbmYgW0lmIGEgc3RyaW5nIGhhcyBhIGxlbmd0aCBncmVhdGVyIHRoYW4gMSBpdCBjYXVzZXMgYW4gZXJyb3IsIG1ha2luZyB0aGlzIHNlbGYgY2hlY2tpbmddKS4KI1JlbW92ZSBib3RoIHRoZSBmaXJzdCBzaXRlIHRoYXQgd2FzIGFuYWx5emVkIGFuZCBhbGwgb2YgdGhlIGFjdGl2ZSBzaXRlcy4gCiAgc2l0ZXMgPC0gc2l0ZXNbLWMoMSwgYWN0aXZlc2l0ZXMpXQoKI0NyZWF0ZSB0aGUgYXJyYXkgdXNpbmcgdGhlIGZpcnN0IG1hdHJpeC4KICBub2FjdGl2ZS5tYXRyaXggPC0gYXJyYXkoZGF0YT1jKGFsbC5EaXN0bWF0cml4MSksIGRpbSA9IGMobGVuZ3RoKGFsaWduLnZlY3RvciksIGxlbmd0aChhbGlnbi52ZWN0b3IpLDEpKQoKI0xvb3AgYWxsIHRoZSBzaXRlcyBzZWxlY3RlZC4gCiAgZm9yIChzaXRlIGluIHNpdGVzKSB7IAogICAgI1NhbWUgbG9naWMgYXMgdGhlIGZpcnN0IG1hdHJpeC4KICAgICAgc2luZ2xlIDwtIGFzLm1hdHJpeChzdHJpbmdkaXN0bWF0cml4KHN0cl9zdWIoYWxpZ24udmVjdG9yLCBzaXRlLCBzaXRlKSwgbWV0aG9kID0gImhhbW1pbmciKSkKICAgICAjQXBwZW5kIHRoZSBuZXcgbWF0cml4IGFsb25nIHRoZSB6IGF4aXMuCiAgICAgIG5vYWN0aXZlLm1hdHJpeCA8LSBhYmluZChzaW5nbGUsIG5vYWN0aXZlLm1hdHJpeCwgYWxvbmcgPSAzKQp9CgojQWRkIHVwIHRoZSB0b3RhbCBudW1iZXIgb2YgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIHByb3RlaW4gYnkgc3VtbWluZyBkb3duIHRoZSB6IGF4aXMgKGRpbXMgPSAyKS4KICBzdW0ubm9hY3RpdmUubWF0cml4IDwtIGFzLm1hdHJpeChyb3dTdW1zKG5vYWN0aXZlLm1hdHJpeCwgZGltcyA9IDIpKSAKCiNOYW1lcy4gCiAgY29sbmFtZXMoc3VtLm5vYWN0aXZlLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQogIHJvd25hbWVzKHN1bS5ub2FjdGl2ZS5tYXRyaXgpIDwtIHByb3RlaW5zJE5hbWUKCiNtYXRyaXggdG8gZGYuCiAgc3VtLm5vYWN0aXZlLmRmIDwtIG1lbHQoc3VtLm5vYWN0aXZlLm1hdHJpeCwgdmFybmFtZXMgPSBjKCJTcGVjaWVzMSIsICJTcGVjaWVzMiIpKQojTmFtZSBDb2x1bW4uIAogIGNvbG5hbWVzKHN1bS5ub2FjdGl2ZS5kZilbM10gPC0gIk5vQWN0aXZlRGlmZiIKCiNNZXJnZSB0byBtYXN0ZXIuIAogIGNvbWJpbmVkLmRmIDwtIG1lcmdlKGNvbWJpbmVkLmRmLCBzdW0ubm9hY3RpdmUuZGYpCgpgYGAKCsKgwqDCoMKgwqBBIHNpbWlsYXIgcGFpcndpc2UgZGlzdGFuY2UgbWV0cmljIHdhcyB0aGVuIHVzZWQgYnV0IGluc3RlYWQgb2YgYW5hbHl6aW5nIHRoZSBhbWlubyBhY2lkcyAqd2l0aG91dCogdGhlIGFjdGl2ZSBzaXRlcywgdGhpcyB0aW1lIHRoZSAzRCBtYXRyaXggd2FzIGNyZWF0ZWQgb25seSBhdCB0aGUgYWN0aXZlIHNpdGVzLCBjcmVhdGluZyBhIDE1eDE1eDQzIHBhaXJ3aXNlIG1hdHJpeCB0aGF0IHdhcyB0aGVuIHN1bW1lZCBhbG9uZyB0aGUgeiBheGlzLiBUaGlzIG1hdHJpeCB3YXMgdGhlbiBtdXRhdGVkIGludG8gYSBkYXRhZnJhbWUgZm9yIGFuYWx5c2lzIChTZWUgXEByZWYobWF0cml4LXRvLWRhdGFmcmFtZSkgZm9yIHZpc3VhbGl6YXRpb24pLgoKYGBge3IgQWN0aXZlc2l0ZXNPbmx5LCByZXN1bHRzID0gJ2hpZGUnLCBlY2hvPVRSVUUsIGNsYXNzLnNvdXJjZSA9ICdmb2xkLXNob3cnfQojQ3JlYXRlIHRoZSBmaXJzdCBtYXRyaXggCiAgYWN0aXZlc2l0ZXMuRGlzdG1hdHJpeDEgPC0gYXMubWF0cml4KHN0cmluZ2Rpc3RtYXRyaXgoc3RyX3N1YihhbGlnbi52ZWN0b3IsIGFjdGl2ZXNpdGVzW1sxXV0sIGFjdGl2ZXNpdGVzW1sxXV0pLCBtZXRob2QgPSAiaGFtbWluZyIpKSAKI09yZGVyIG9mIE9wZXJhdGlvbnM6CiAgI3N0cl9zdWI6IENyZWF0ZSBhIHZlY3RvciBvZiB0aGUgcHJvdGVpbiBhdCB0aGUgZmlyc3QgYWN0aXZlIHNpdGUuIAogICNzdHJpbmdkaXN0bWF0cml4OiBEb2VzIGEgc2ltcGxlIGNvbXBhcmlzb24gbWF0cml4IGJldHdlZW4gZWFjaCBncm91cCAoMCA9IGlkZW50aWNhbCwgMSA9IGRpZmZlcmVuY2UpIHVzaW5nIEhhbW1pbmcgbWV0aG9kb2xvZ3kgKGNvdW50cyB0aGUgbnVtYmVyIG9mIGNoYXJhY3RlciBzdWJzdGl0dXRpb25zIHRoYXQgdHVybnMgYiBpbnRvIGEuIElmIGEgYW5kIGIgaGF2ZSBkaWZmZXJlbnQgbnVtYmVyIG9mIGNoYXJhY3RlcnMgdGhlIGRpc3RhbmNlIGlzIEluZiBbSWYgYSBzdHJpbmcgaGFzIGEgbGVuZ3RoIGdyZWF0ZXIgdGhhbiAxIGl0IGNhdXNlcyBhbiBlcnJvciwgbWFraW5nIHRoaXMgc2VsZiBjaGVja2luZ10pLgogIAojUmVtb3ZlIHRoZSBhbmFseXplZCBzaXRlIGZyb20gdGhlIHZlY3RvciB0byBwcmV2ZW50IHJlcGVhdCBhbmFseXNpcy4gCiAgYWN0aXZlc2l0ZXMgPC0gYWN0aXZlc2l0ZXNbLTFdCgojQ3JlYXRlIHRoZSBhcnJheSB1c2luZyB0aGUgZmlyc3QgbWF0cml4IGFzIG91ciBpbnB1dCBkYXRhLiAKICBhY3RpdmVzaXRlcy5tYXRyaXggPC0gYXJyYXkoZGF0YT1jKGFjdGl2ZXNpdGVzLkRpc3RtYXRyaXgxKSwgZGltID0gYyhsZW5ndGgoYWxpZ24udmVjdG9yKSwgbGVuZ3RoKGFsaWduLnZlY3RvciksMSkpCgogIAojTG9vcGluZyBhbGwgdGhlIG1hdHJpeCBzaXRlcy4gCmZvciAoc2l0ZSBpbiBhY3RpdmVzaXRlcykgeyAKI1NhbWUgYXMgdGhlIGZpcnN0IG1hdHJpeC4gCiAgc2luZ2xlIDwtIGFzLm1hdHJpeChzdHJpbmdkaXN0bWF0cml4KHN0cl9zdWIoYWxpZ24udmVjdG9yLCBzaXRlLCBzaXRlKSwgbWV0aG9kID0gImhhbW1pbmciKSkgCiNBcHBlbmQgdGhlIG5ldyBtYXRyaXggYWxvbmcgdGhlIHogYXhpcyB0byB0aGUgM0QgYXJyYXkuIAogIGFjdGl2ZXNpdGVzLm1hdHJpeCA8LSBhYmluZChzaW5nbGUsIGFjdGl2ZXNpdGVzLm1hdHJpeCwgYWxvbmcgPSAzKSAKfQoKI0Rpc3RhbmNlIG1hdHJpeCBzdW1tZWQuCiAgYWN0aXZlc2l0ZXMuZGlzdC5hbGwubWF0cml4IDwtIHJvd1N1bXMoYWN0aXZlc2l0ZXMubWF0cml4LCBkaW1zID0gMikKICAjQWRkIHVwIHRoZSB0b3RhbCBudW1iZXIgb2YgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIHByb3RlaW4gYnkgc3VtbWluZyBkb3duIHRoZSB6IGF4aXMgKGRpbXMgPSAyKS4KCiNEaXN0YW5jZSBvdXRwdXQKICBhY3RpdmVzaXRlcy5kaXMuYWxsLmRpc3QgPC0gYXMuZGlzdChyb3dTdW1zKGFjdGl2ZXNpdGVzLm1hdHJpeCwgZGltcyA9IDIpKSAKICAjVGhpcyBpcyBmb3IgdXNlciByZWZlcmVuY2UsIGl0IGlzIG5vdCBhbmFseXplZCBieSB0aGUgc2NyaXB0LiAKCiNOYW1lIHRoZSBNYXRyaXguIAogIGNvbG5hbWVzKGFjdGl2ZXNpdGVzLmRpc3QuYWxsLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQogIHJvd25hbWVzKGFjdGl2ZXNpdGVzLmRpc3QuYWxsLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQoKI21hdHJpeCAtPiBkYXRhZnJhbWUuIAogIGFjdGl2ZXNpdGVzLmRpc3QuYWxsLmRmIDwtIG1lbHQoYWN0aXZlc2l0ZXMuZGlzdC5hbGwubWF0cml4LCB2YXJuYW1lcyA9IGMoIlNwZWNpZXMxIiwgIlNwZWNpZXMyIikpCiNOYW1lIHRoZSBuZXcgY29sdW1uCiAgY29sbmFtZXMoYWN0aXZlc2l0ZXMuZGlzdC5hbGwuZGYpWzNdIDwtICJBY3RpdmVTaXRlc09ubHkiCgojTWVyZ2UgdGhpcyBkYXRhZnJhbWUgd2l0aCB0aGUgbWFzdGVyIGRhdGFmcmFtZS4gCiAgY29tYmluZWQuZGYgPC0gbWVyZ2UoY29tYmluZWQuZGYsIGFjdGl2ZXNpdGVzLmRpc3QuYWxsLmRmKQpgYGAKCsKgwqDCoMKgwqBUaGUgZGF0YWZyYW1lIGNvbnRhaW5pbmcgdGhlIHNwZWNpZXMgY29tcGFyZWQsIHRoZSBlbWlzc2lvbiBzcGVjdHJhLCBhbmQgdGhlIG51bWJlciBvZiBkaWZmZXJlbmNlcyBhdCB0aGUgdGhyZWUgZ3JvdXBzIHdhcyB0aGVuIGNsZWFuZWQgdG8gcmVtb3ZlIGFueSBzZWxmIGNvbXBhcmlzb25zIGFuZCBkdXBsaWNhdGUgY29tcGFyaXNvbnMgY3JlYXRlZCBkdXJpbmcgdGhlIGNvbnZlcnNpb24gZnJvbSBhIG1hdHJpeCB0byBkYXRhZnJhbWUuCgpgYGB7ciBDbGVhbmluZywgZWNobz1UUlVFLCByZXN1bHRzPSdoaWRlJywgY2xhc3Muc291cmNlID0nZm9sZC1zaG93J30KCiNMb2dpYyBmb3VuZCBhdDpodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMzQ3NDcyOS9jb252ZXJ0LW9iamVjdC1vZi1jbGFzcy1kaXN0LWludG8tZGF0YS1mcmFtZS1pbi1yCiNSZW1vdmUgRHVwbGljYXRlcyBhbmQgCiAgI1NvcnQgdGhlIHR3byBjb2x1bW5zLgogICAgbmFtZXMgPC0gdChhcHBseShjb21iaW5lZC5kZlssYygxLDIpXSwxLEZVTj1zb3J0KSkgCiAgI0ZpbmQgcm93cyBjb21wYXJpbmcgdGhlIHNhbWUgb3JnYW5pc20uIAogICAgc2FtZSA8LSB3aGljaChuYW1lc1ssMV0gPT0gbmFtZXNbLDJdKSAKICAjTWVyZ2UgbmFtZXMgY29sdW1ucyBpbnRvIHNpbmdsZSBjb2x1bW4gc2VwYXJhdGVkIGJ5IHwuCiAgICBuYW1lcyAgICA8LSBwYXN0ZShuYW1lc1ssMV0sbmFtZXNbLDJdLHNlcD0ifCIpIAogICNmaW5kIGR1cGxpY2F0ZSBjb21wYXJpc29ucy4KICAgIGR1cHMgPC0gd2hpY2goZHVwbGljYXRlZChuYW1lcykpIAogICMgUmVtb3ZlIGFueSBzYW1lIG9yZ2FuaXNtIG9yIGR1cGxpY2F0ZXMgCiAgY29tYmluZWQuZGYgPC0gY29tYmluZWQuZGZbLWMoc2FtZSwgZHVwcyksXSAKCnJtKGR1cHMsIG5hbWVzLCBzYW1lKQoKY29tYmluZWQuZGYkU3BlY2llczEgPC0gZ3N1YignXycsICcgJywgY29tYmluZWQuZGYkU3BlY2llczEpCmNvbWJpbmVkLmRmJFNwZWNpZXMyIDwtIGdzdWIoJ18nLCAnICcsIGNvbWJpbmVkLmRmJFNwZWNpZXMyKQoKI09ubHkgZ2V0IHRoZSB3YXZlbGVuZ3RoIGVtaXNzaW9uIHNwZWN0cmEgb2YgdGhlIHNwZWNpZXMKY29tYmluZWQuZGYkU3BlY2llczEuYWJyIDwtIHN0cl9zdWIoY29tYmluZWQuZGYkU3BlY2llczEsIDEsMikKY29tYmluZWQuZGYkU3BlY2llczIuYWJyIDwtIHN0cl9zdWIoY29tYmluZWQuZGYkU3BlY2llczIsIDEsMikKCgojQWJyIGNvbCBjb21wYXJpc29uCmNvbWJpbmVkLmRmJENvbXBhcmlzb24uYWJyIDwtIHN0cl9jKGNvbWJpbmVkLmRmJFNwZWNpZXMxLmFiciwgIi8iLCBjb21iaW5lZC5kZiRTcGVjaWVzMi5hYnIpCiNGdWxsIE5hbWUgQ29tcGFyaXNvbgpjb21iaW5lZC5kZiRDb21wYXJpc29uLmZ1bGwgPC0gc3RyX2MoY29tYmluZWQuZGYkU3BlY2llczEsICIvIiwgY29tYmluZWQuZGYkU3BlY2llczIpCgoKI29yZ2FuaXplIHRoZSBjb21wYXJpc29ucyBmcm9tIGdyZWVuIHRvIHllbGxvdy4gCmNvbWJpbmVkLmRmJENvbXBhcmlzb24uYWJyIDwtIGZhY3Rvcihjb21iaW5lZC5kZiRDb21wYXJpc29uLmFiciwgbGV2ZWxzID0gYygiR1IvR1IiLCAiR1IvWUUiLCAiR1IvWUciLCAiWUcvWUciLCAiWUUvWUciLCAiWUUvWUUiKSkKCgoKY29sb3JzIDwtIGMoIiMwNzQwMDAiLCAiI2FlZmYxNyIsICIjNjZkYjAwIiwgIiM2OTk2NDciLCAiIzI2YjUzMCIsICJibHVlIikKCmBgYAoKwqDCoMKgwqDCoEZpbmFsbHksIHRoZXNlIHBhaXJ3aXNlIGNvbXBhcmlzb25zIHdlcmUgZ3JhcGhlZCB1c2luZyBhIGNvbWJpbmF0aW9uIG9mIGdncGxvdDIgW0BSLWdncGxvdDJdLCBncGxvdHMgW0BSLWdwbG90c10sIGFuZCBwbG90bHkgW0BSLXBsb3RseV0gdG8gY3JlYXRlIGJvdGggaGVhdG1hcHMgb2YgdGhlIHN1bW1lZCBkaWZmZXJlbmNlcyBhbmQgc2NhdHRlcnBsb3RzIGNvbXBhcmluZyB0aGUgYWJzb2x1dGUgY2hhbmdlIGluIGVtaXNzaW9uIHNwZWN0cmEgdnMuIHRoZSBkaWZmZXJlbmNlIGluIGFtaW5vIGFjaWQgcmVzaWR1ZXMuIEZvciBhIHZpc3VhbGl6ZWQgd29ya2Zsb3csIHNlZSBcQHJlZihmaWc6U1RGMSkuCgojIFJlc3VsdHMKCiMjIFBoeWxvZ2VuZXRpY3MKCkFmdGVyIGV4dHJhY3RpbmcgdGhlIHRoaXJkIGNvZG9uIG9ubHkgYW5kIHJ1bm5pbmcgSVEtdHJlZSwgYSBtYXhpbXVtIGxpa2VsaWhvb2QgdHJlZSB3YXMgYnVpbHQgdXNpbmcgR1RSK0YrRzQgYXMgdGhlIHNlbGVjdGVkIHN1YnN0aXR1dGlvbiBtb2RlbC4gQXMgc2hvd24gaW4gRmlndXJlIFxAcmVmKGZpZzpQaHlsb2dlbmV0aWNzKSwgbm8gbW9ub3BoeWxldGljIGdyb3VwaW5nIHdhcyBlc3RhYmxpc2hlZCBiZXR3ZWVuIGRpZmZlcmVudCBjb2xvciBjYXRlZ29yaWVzLiBGdXJ0aGVybW9yZSwgdGhlIHR3byAqTGkuIGNydWNpYXRhKiBncm91cCB0b2dldGhlciBpbnRvIGEgdW5pcXVlIGNsYWRlLCBkZXNwaXRlIGhhdmluZyBkaWZmZXJlbnQgZW1pc3Npb24gc3BlY3RyYS4gV2hpbGUgdGhpcyB0cmVlIGRvZXMgaGF2ZSBsb3cgYm9vdHN0cmFwIHN1cHBvcnQgdmFsdWVzLCBpdCBoYXMgc2ltaWxhciBicmFuY2hpbmcgdG8gdGhhdCBvZiBAb2JhUmVzdXJyZWN0aW5nQW5jaWVudEdsb3cyMDIwLCBwcm92aWRpbmcgc3VwcG9ydCB0byB0aGUgZXZvbHV0aW9uYXJ5IGhpc3Rvcnkgb2YgdGhpcyB0cmVlLgoKYGBge3IgUGh5bG9nZW5ldGljcywgZmlnLmNhcD0iUGh5bG9nZW5ldGljIHRyZWUgb2YgdGhlIGFuYWx5emVkIHNwZWNpZXMgKEJvb3RzdHJhcHMgPSAxMCwwMDAsIG1ldHJpYyA9IEFJQyksIENvbG9yLWNvZGluZyBtYW51YWxseSBtdXRhdGVkLiIsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSIxMTAwJSIsIGVjaG89RkFMU0V9CgogICAga25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkltYWdlcy9QaHlsb2dlbmV0aWNUcmVlLmpwZyIpCgpgYGAKCiMjIFBhaXJ3aXNlIERpc3RhbmNlIEFuYWx5c2lzCgpUaGUgdGhyZWUgZGlmZmVyZW50IGFycmF5cyB3ZXJlIHN1bW1lZCBhbG9uZyB0aGUgeiBheGlzIGludG8gdGhyZWUgMi1kaW1lbnNpb25hbCBtYXRyaWNlcywgd2hpY2ggd2VyZSB0aGVuIHBsb3R0ZWQgYXMgYSBoZWF0bWFwIGFuZCBhZ2FpbnN0IHRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGluIGVtaXNzaW9uIHNwZWN0cmE6CgpgYGB7ciBBbGxTaXRlc0hlYXRtYXAsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmNhcD0iSGVhdG1hcCBkaXNwbGF5aW5nIHRoZSB0b3RhbCBudW1iZXIgb2YgYW1pbm8gYWNpZCBkaWZmZXJlbmNlcyBiZXR3ZWVuIGVhY2ggc3BlY2llcy4ifQoKCgoKaGVhdG1hcC4yKHN1bS5hbGwubWF0cml4LCAKICAgICAgICAgIFJvd3YgPSBGQUxTRSwgCiAgICAgICAgICBDb2x2ID0gRkFMU0UsIAogICAgICAgICAgZGVuZHJvZ3JhbSA9ICJub25lIiwgCiAgICAgICAgICBzeW1tID0gVFJVRSwgCiAgICAgICAgICBzY2FsZSA9ICJub25lIiwgCiAgICAgICAgICB0cmFjZSA9ICJub25lIiwgCiAgICAgICAgICBtYXJnaW5zID0gYygxMS41LDEwKSwgCiAgICAgICAgICBjZWxsbm90ZSA9IHN1bS5hbGwubWF0cml4LAogICAgICAgICAgbm90ZWNvbCA9ICJibGFjayIsIAogICAgICAgICAgY2V4Um93ID0gMC43CiAgICAgICAgICApCmBgYAoKYGBge3IgQWxsU2l0ZXNTY2F0dGVyUGxvdCwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJJbnRlcmFjdGl2ZSBzY2F0dGVyLXBsb3Qgb2YgdGhlIGFic29sdXRlIGNoYW5nZSBpbiBlbWlzc2lvbiBzcGVjdHJhIHZzLiB0aGUgdG90YWwgbnVtYmVyIG9mIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIHNwZWNpZXMuIiwgd2FybmluZz1GQUxTRX0Kc3VtLmFsbC5wbG90IDwtIGdncGxvdChjb21iaW5lZC5kZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGFicy5lbWlzc2lvbi5kaWZmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9QWxsRGlmZiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9Q29tcGFyaXNvbi5hYnIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gQ29tcGFyaXNvbi5mdWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlPUNvbXBhcmlzb24uYWJyKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBzdGF0X2VsbGlwc2UoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpICsKICB4bGFiKCJBYnNvbHV0ZSDiiIYgRW1pc3Npb24gU3BlY3RyYSIpICsKICB5bGFiKCJUb3RhbCBOdW1iZXIgb2YgQUEgRGlmZmVyZW5jZXMiKSArIAogIGxhYnMoY29sb3IgPSAiQ29tcGFyaXNvbiBHcm91cCIsIHNoYXBlID0gIkNvbXBhcmlzb24gR3JvdXAiKQogIAojSW50ZXJhY3RpdmUgcGxvdAogIGdncGxvdGx5KHN1bS5hbGwucGxvdCkgCgpgYGAKCmBgYHtyIE5vQWN0aXZlSGVhdG1hcCwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJIZWF0bWFwIGRpc3BsYXlpbmcgdGhlIHRvdGFsIG51bWJlciBvZiBhbWlubyBhY2lkIGRpZmZlcmVuY2VzLCBleGNsdWRpbmcgYWN0aXZlIHNpdGVzLCBiZXR3ZWVuIGVhY2ggc3BlY2llcy4ifQpoZWF0bWFwLjIoc3VtLm5vYWN0aXZlLm1hdHJpeCwgCiAgICAgICAgICBSb3d2ID0gTkEsIAogICAgICAgICAgQ29sdiA9IE5BLCAKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsIAogICAgICAgICAgc3ltbSA9IFRSVUUsIAogICAgICAgICAgc2NhbGUgPSAibm9uZSIsIAogICAgICAgICAgdHJhY2UgPSAibm9uZSIsIAogICAgICAgICAgbWFyZ2lucyA9IGMoMTEuNSwxMCksIAogICAgICAgICAgY2VsbG5vdGUgPSBzdW0ubm9hY3RpdmUubWF0cml4LCAKICAgICAgICAgIG5vdGVjb2wgPSAiYmxhY2siLCAKICAgICAgICAgIGNleFJvdyA9IDAuNwogICAgICAgICAgKQpgYGAKCmBgYHtyIFNjYXR0ZXJOb0FjdGl2ZSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuY2FwPSJJbnRlcmFjdGl2ZSBzY2F0dGVyLXBsb3Qgb2YgdGhlIGFic29sdXRlIGNoYW5nZSBpbiBlbWlzc2lvbiBzcGVjdHJhIHZzLiB0aGUgdG90YWwgbnVtYmVyIG9mIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMsIGV4Y2x1ZGluZyBhY3RpdmUgc2l0ZXMsIGJldHdlZW4gZWFjaCBzcGVjaWVzLiIsIHdhcm5pbmc9RkFMU0V9CiNnZ3Bsb3QyIC0gQWxsIGFlc3RoZXRpY3MgYXJlIHNlbGYtZXhwbGFpbmF0b3J5LiAKc3VtLm5vYWN0aXZlLnBsb3QgPC0gZ2dwbG90KGNvbWJpbmVkLmRmLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gYWJzLmVtaXNzaW9uLmRpZmYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1Ob0FjdGl2ZURpZmYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPUNvbXBhcmlzb24uYWJyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IENvbXBhcmlzb24uZnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGFwZT1Db21wYXJpc29uLmFicikpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgc3RhdF9lbGxpcHNlKCkgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JzKSArCiAgeGxhYigiQWJzb2x1dGUg4oiGIEVtaXNzaW9uIFNwZWN0cmEiKSArCiAgeWxhYigiVG90YWwgTnVtYmVyIG9mIEFBIERpZmZlcmVuY2VzIHcvbyBBY3RpdmUgU2l0ZXMiKSArCiAgbGFicyhjb2xvciA9ICJDb21wYXJpc29uIEdyb3VwIiwgc2hhcGUgPSAiQ29tcGFyaXNvbiBHcm91cCIpCiAgCiNJbnRlcmFjdGl2ZSBwbG90LgogIGdncGxvdGx5KHN1bS5ub2FjdGl2ZS5wbG90KSAKCmBgYAoKYGBge3IgQWN0aXZlU2l0ZXNIZWF0bWFwLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5jYXA9IkhlYXRtYXAgZGlzcGxheWluZyB0aGUgdG90YWwgbnVtYmVyIG9mIGFjdGl2ZSBzaXRlIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIHNwZWNpZXMuIn0KaGVhdG1hcC4yKGFjdGl2ZXNpdGVzLmRpc3QuYWxsLm1hdHJpeCwgCiAgICAgICAgICBSb3d2ID0gTkEsIAogICAgICAgICAgQ29sdiA9IE5BLCAKICAgICAgICAgIGRlbmRyb2dyYW0gPSAibm9uZSIsIAogICAgICAgICAgc3ltbSA9IFRSVUUsIAogICAgICAgICAgc2NhbGUgPSAibm9uZSIsIAogICAgICAgICAgdHJhY2UgPSAibm9uZSIsIAogICAgICAgICAgbWFyZ2lucyA9IGMoMTEuNSwxMCksIAogICAgICAgICAgY2VsbG5vdGUgPSBhY3RpdmVzaXRlcy5kaXN0LmFsbC5tYXRyaXgsIAogICAgICAgICAgbm90ZWNvbCA9ICJibGFjayIsIAogICAgICAgICAgY2V4Um93ID0gMC43CiAgICAgICAgICApCmBgYAoKYGBge3IgQWN0aXZlU2l0ZXNTY2F0dGVyLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy5jYXA9IkludGVyYWN0aXZlIHNjYXR0ZXItcGxvdCBvZiB0aGUgYWJzb2x1dGUgY2hhbmdlIGluIGVtaXNzaW9uIHNwZWN0cmEgdnMuIHRoZSB0b3RhbCBudW1iZXIgb2YgYWN0aXZlIHNpdGUgYW1pbm8gYWNpZCBkaWZmZXJlbmNlcywgZXhjbHVkaW5nIGFjdGl2ZSBzaXRlcywgYmV0d2VlbiBlYWNoIHNwZWNpZXMuIiwgd2FybmluZz1GQUxTRX0Kc3VtLmFjdGl2ZW9ubHkucGxvdCA8LSBnZ3Bsb3QoY29tYmluZWQuZGYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBhYnMuZW1pc3Npb24uZGlmZiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5PUFjdGl2ZVNpdGVzT25seSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9Q29tcGFyaXNvbi5hYnIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gQ29tcGFyaXNvbi5mdWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlPUNvbXBhcmlzb24uYWJyKSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICBzdGF0X2VsbGlwc2UoKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnMpICsKICB4bGFiKCJBYnNvbHV0ZSDiiIYgRW1pc3Npb24gU3BlY3RyYSIpICsKICB5bGFiKCJUb3RhbCBOdW1iZXIgb2YgQWN0aXZlIFNpdGVzIEFBIGRpZmZlcmVuY2VzIikgKwogIGxhYnMoY29sb3IgPSAiQ29tcGFyaXNvbiBHcm91cCIsIHNoYXBlID0gIkNvbXBhcmlzb24gR3JvdXAiKQogIAojSW50ZXJhY3RpdmUgcGxvdAogIGdncGxvdGx5KHN1bS5hY3RpdmVvbmx5LnBsb3QpIAoKYGBgCgrCoMKgwqDCoMKgQWNyb3NzIGFsbCBvZiB0aGVzZSBmaWd1cmVzLCBubyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBlbWlzc2lvbiBzcGVjdHJhIGVtaXR0ZWQgYW5kIHRoZSBudW1iZXIgb2YgYW1pbm8gYWNpZCBkaWZmZXJlbmNlcyBjb3VsZCBiZSBlbHVjaWRhdGVkLiBUaGUgaW50cmFjb21wYXJpc29ucyBvZiB0aGUgeWVsbG93IGdyb3VwIHJldmVhbHMgdGhhdCBkZXNwaXRlIHRoZSAqTGwuIGNydWNpYXRhKiBoYXZpbmcgYSBtYXhpbXVtIGRpZmZlcmVuY2UgaW4gZW1pc3Npb24gc3BlY3RyYSBvZiA4bm0gKCpMbCBwYXJ2dWxhKiwgNTY4bm0pLCB0aGlzIHNwZWNpZXMgaGFzIG92ZXIgMTAwIHRvdGFsIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgYmV0d2VlbiBlYWNoIG90aGVyIHllbGxvdyBzcGVjaWVzLiBUaGlzIGlzIGluIHNoYXJwIGNvbnRyYXN0IHRvIG90aGVyIGludHJhLWNvbG9yIHNwZWNpZSBjb21wYXJpc2lvbnMgd2hvIG9ubHkgaGF2ZSBiZXR3ZWVuIDYgYW5kIDI4IHRvdGFsIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMuIEFkZGl0aW9uYWxseSwgd2hlbiBicm91Z2h0IHRvIHRoZSBsZXZlbCBvZiBhY3RpdmUgc2l0ZXMsIHRoZSB5ZWxsb3cgc3BlY2llcyBoYWQgMCBkaWZmZXJlbmNlcyBpbiBhbWlubyBhY2lkIHJlc2lkdWVzLCB3aXRoIHRoZSBleGNlcHRpb24gb2YgKkxsLiBjcnVjaWF0YSogd2l0aCAyIGRpZmZlcmVuY2VzLiBJbiBvdGhlciB3b3JkcywgYWxsIG9mIHRoZSBhbWlubyBhY2lkIGRpZmZlcmVuY2VzIHdlcmUgZm91bmQgaW4gYXJlYXMgdGhhdCBhcmUgbm90IGRpcmVjdGx5IGludGVyYWN0aW5nIHdpdGggdGhlIGx1Y2lmZXJpbiBzdWJzdHJhdGUuCgrCoMKgwqDCoMKgT2YgcGFydGljdWxhciBpbnRlcmVzdCBhcmUgMiAqTGkuIGNydWNpYXRhKiBMdWMxLCBvbmUgdGhhdCBlbWl0cyBhIHBlYWsgd2F2ZWxlbmd0aCBvZiA1NjVubSAoeWVsbG93LCBBY2Nlc3Npb24gI00yNjE5NCksIGFuZCB0aGUgb3RoZXIgd2hpY2ggZW1pdHMgYSBwZWFrIHdhdmVsZW5ndGggb2YgNTU0ICh5ZWxsb3ctZ3JlZW4gd2F2ZWxlbmd0aCwgQWNjZXNzaW9uICNBQjIyMDE2MikuIFdoaWxlIG1vc3Qgb3RoZXIgc3BlY2llcyBoYXZlIG11bHRpcGxlIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgYXQgYm90aCBhbGwgYW1pbm8gYWNpZHMgYW5kIHRoZSBhY3RpdmUgc2l0ZXMsIHRoZXNlIHR3byBzcGVjaWVzIGhhdmUgb25seSA1IGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgYXQgbm9uLWFjdGl2ZSBzaXRlcywgYW5kIGFuIGFic29sdXRlIGNoYW5nZSBpbiBwZWFrIGVtaXNzaW9uIHNwZWN0cmEgb2YgNy4KCsKgwqDCoMKgwqBGb3IgdGhlIG90aGVyIGNvbG9yIGNhdGVnb3JpZXMsIHdoaWxlIHRoZSBpbnRyYS1jb21wYXJpc29ucyBoYXZlIGEgc2xpZ2h0bHkgbG93ZXIgbnVtYmVyIG9mIGRpZmZlcmVuY2VzIHRoYW4gaW50ZXItZ3JvdXAgY29tcGFyaXNvbnMsIHRoZXJlIGlzIHN0aWxsIGEgaGlnaCBkZWdyZWUgb2YgZGlmZmVyZW5jZXMgaW4gZW1pc3Npb24gc3BlY3RyYS4gRXZlbiB3aGVuIGFjY291bnRpbmcgZm9yIGp1c3QgYWN0aXZlIHNpdGVzLCB0aGVyZSBpcyBldmVuIGxlc3Mgb2YgYSBjb3JyZWxhdGlvbiBhcyBlYWNoIGdyb3VwIHdhcyBoaWdobHkgb3ZlcmxhcHBpbmcgd2l0aCBlYWNoIG90aGVyLiBGdXJ0aGVybW9yZSwgdGhlcmUgYXJlIGEgY291cGxlIG9mIGNvbXBhcmlzb25zIHdoZXJlIGRlc3BpdGUgaGF2aW5nIG5vIGRpZmZlcmVuY2UgaW4gcGVhayBlbWlzc2lvbiB3YXZlbGVuZ3RoLCB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gYW1pbm8gYWNpZCByZXNpZHVlcy4gQ29sbGVjdGl2ZWx5LCB0aGVzZSBncmFwaHMgc2hvdyB0aGF0IHRoZSBhbWlubyBhY2lkIHJlc2lkdWVzIGFyZSBub3QgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgY29udHJpYnV0aW9uIHRvd2FyZHMgdGhlIGNvbG9yIGVtaXNzaW9uIGVtaXR0ZWQgZHVyaW5nIGJpb2x1bWluZXNjZW5jZS4KCiMgRGlzY3Vzc2lvbgoKwqDCoMKgwqDCoFBoeWxvZ2VuZXRpY2FsbHksIHRoaXMgZGF0YSBzaG93cyB0aGF0IHRoZXJlIGlzIG5vIGV2b2x1dGlvbmFyeSBjb3JyZWxhdGlvbiB0byB0aGUgd2F2ZWxlbmd0aCBzcGVjdHJhIGVtaXR0ZWQgYnkgYSBmaXJlZmx5LiBDb21wYXJpbmcgdGhpcyB0cmVlIHRvIHRoYXQgb2YgQG9iYVJlc3VycmVjdGluZ0FuY2llbnRHbG93MjAyMCAoRmlndXJlIFxAcmVmKGZpZzpGaWd1cmUyKSksIGl0IGlzIGludGVyZXN0aW5nIHRvIHNlZSB0aGUgc3BlY2llcyBhcmUgZ3JvdXBpbmcgc2ltaWxhcmx5IGFsb25nIHRoZSBwaHlsb2dlbmV0aWMgbGluZWFnZSwgZGVzcGl0ZSBPYmEgZXQgYWwuIHVuZGVyZ29pbmcgYSBkaWZmZXJlbmNlIHNlcmllcyBvZiBzdGVwcyBhbmQgdXNpbmcgYSBkaWZmZXJlbnQgc3Vic3RpdHV0aW9uIG1vZGVsIChKVFQgbWF0cml4IHZzIEdUUitGK0c0KS4gU2luY2UgdGhlIG11dGF0aW9ucyB1bmRlcnRha2VuIHJlbW92ZWQgdGhlIHBvc3NpYmlsaXR5IG9mIGNvbnZlcmdlbnQgZXZvbHV0aW9uLCB0aGlzIGRhdGEgc3VnZ2VzdHMgdGhhdCBldm9sdXRpb25hcmlseSwgdGhlIGFtaW5vIGFjaWQgcmVzaWR1ZXMgcHJlc2VudCB3aXRoaW4gYSBzcGVjaWVzIGFyZSBub3QgYSBwcmltYXJ5IGRldGVybWluYW50IG9mIHRoZSBjb2xvciBzcGVjdHJhIGVtaXR0ZWQuIElmIHRoaXMgd2VyZSB0aGUgY2FzZSwgaXQgd291bGQgYmUgZXhwZWN0ZWQgdG8gc2VlIHRoZSB0cmVlIHN0YXJ0IHdpdGggcmVkICh0aGUgZGVzaWduYXRlZCBvdXRncm91cCBjb2xvcikgYW5kIGhhdmUgbW9ub3BoeWxldGljIGNsYWRlcyBvZiB5ZWxsb3csIHllbGxvdy1ncmVlbiwgYW5kIGdyZWVuLCBpZGVudGljYWwgdG8gdGhhdCBvZiB0aGUgY29sb3Igc3BlY3RydW0uCgrCoMKgwqDCoMKgVGhlc2UgY29uY2x1c2lvbnMgYXJlIGZ1cnRoZXIgYmFja2VkIGJ5IHRoZSBoZWF0LW1hcHMgYW5kIHNjYXR0ZXItcGxvdHMgc2hvd2luZyBsaXR0bGUgdG8gbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgbnVtYmVyIG9mIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgYW5kIHRoZSBhYnNvbHV0ZSBjaGFuZ2UgaW4gcGVhayBlbWlzc2lvbiBzcGVjdHJhLiBJbiBmYWN0LCB0aGUgcmVzdWx0cyBvZiB0aGUgd2hvbGUgcHJvdGVpbiBhbmQgd2l0aG91dCBhY3RpdmUgc2l0ZSBhbmFseXNpcyBzdWdnZXN0cyB0aGF0IGRlc3BpdGUgaGF2aW5nIGEgaGlnaCBudW1iZXIgYSBoaWdoIG51bWJlciBvZiBkaWZmZXJlbmNlcyBpbiBhbWlubyBhY2lkIHJlc2lkdWVzIGFjcm9zcyB0aGUgd2hvbGUgcHJvdGVpbiwgdGhlcmUgaXMgYSBzbWFsbCBjaGFuZ2UgaW4gdGhlIGFic29sdXRlIGVtaXNzaW9uIHNwZWN0cmEgYmV0d2VlbiBjb21wYXJpc29uIGNvbG9ycy4KCsKgwqDCoMKgwqBGdXJ0aGVybW9yZSwgdGhlIGludHJhLSBhbmQgaW50ZXItY2F0ZWdvcmljYWwgY29tcGFyaXNvbnMgaGF2aW5nIGEgbGFyZ2UgbnVtYmVyIG9mIGRpZmZlcmVuY2VzIGluIGFtaW5vIGFjaWQgcmVzaWR1ZXMgZGVzcGl0ZSBoYXZpbmcgYSBzbWFsbCBjaGFuZ2UgaW4gcGVhayBlbWlzc2lvbiBzcGVjdHJhIHN1Z2dlc3RzIHRoYXQgYSBzaWduaWZpY2FudCBwb3J0aW9uIG9mIHRoZSBhbWlubyBhY2lkIHJlc2lkdWVzIGRvIG5vdCBwbGF5IGEgcm9sZSBpbiB0aGUgZW1pc3Npb24gc3BlY3RyYSBhIHNwZWNpZXMgZW1pdHMuIEhvd2V2ZXIsIGZ1cnRoZXIgdGVzdGluZyB3b3VsZCBiZSByZXF1aXJlZCB0byBzdXBwb3J0IHRoaXMgaHlwb3RoZXNpcy4KCsKgwqDCoMKgwqBMb29raW5nIGludG8gYWN0aXZlIHNpdGVzLCB0aGUgeWVsbG93IHdhdmVsZW5ndGggY2F0ZWdvcnkgaGF2aW5nIDAgYWN0aXZlIHNpdGUgZGlmZmVyZW5jZXMsIHdpdGggdGhlIGV4Y2VwdGlvbiBvZiAqTGwuIGNydWNpYXRhKiB3aGljaCBoYXMgMiBkaWZmZXJlbmNlcywgZGVzcGl0ZSBjb250aW51aW5nIHRvIGhhdmUgYSBkaWZmZXJlbmNlIGluIHBlYWsgZW1pc3Npb24gc3BlY3RyYS4gV2hpbGUgdGhpcyBzdWJzZXQgc3VnZ2VzdHMgdGhhdCB0aGUgcmVzaWR1ZXMgYXQgYW4gYWN0aXZlIHNpdGUgY291bGQgcGxheSBzb21lIHJvbGUgaW4gdGhlIHdhdmVsZW5ndGggZW1pdHRlZCBieSBhIHNwZWNpZXMsIGFzIGluZGljYXRlZCBieSB0aGUgZGlmZmVyZW5jZXMgaW4gYW1pbm8gYWNpZCByZXNpZHVlcyB3aGVuIGNvbXBhcmVkIHRvIG90aGVyIGNvbG9yIGdyb3VwcywgdGhlIG90aGVyIGNhdGVnb3JpZXMgcmVqZWN0IHRoaXMgYnkgKkxsLiBjcnVjaWF0YSogKHllbGxvdyksIGhhdmluZyBubyBhY3RpdmUgc2l0ZSBkaWZmZXJlbmNlcyB0byAqTGwuIGNydWNpYXRhKiAoeWVsbG93LWdyZWVuKSBhbmQgKkEuIGxhdGVyYWxpcyosIGRlc3BpdGUgaGF2aW5nIGFuIGFic29sdXRlIGNoYW5nZSBpbiBlbWlzc2lvbiBzcGVjdHJhIG9mIDggYW5kIDEwIHJlc3BlY3RpdmVseS4KCsKgwqDCoMKgwqBUaGVyZSBpcyBldmVuIGxlc3Mgb2YgYSBjb3JyZWxhdGlvbiB3aXRoIGVhY2ggZ3JvdXAgYmVpbmcgaGlnaGx5IHNwcmVhZCBhY3Jvc3MgdGhlIHNjYXR0ZXJwbG90IGFuZCBub3QgY2x1c3RlcmluZyBpbnRvIGRpc3RpbmN0IGdyb3VwcyBvciBhbG9uZyBhIGxpbmVhciBtb2RlbCBhcyBwcmVkaWN0ZWQuIFRoZXNlIGZldywgaWYgYW55LCBudW1iZXIgb2YgZGlmZmVyZW5jZXMgYWNyb3NzIG92ZXIgNDAgYW1pbm8gYWNpZCBhY3RpdmUgc2l0ZXMgaW5kaWNhdGVzIHRoYXQgdGhlc2Ugc2l0ZXMgY291bGQgbGlrZWx5IGJlIHVuZGVyIHNvbWUgZm9ybSBvZiBjb25zdHJhaW50IHRvIGVuYWJsZSBiaW9sdW1pbmVzY2VuY2Ugd2l0aGluIHRoZSBmaXJlZmx5LCBob3dldmVyIGZ1cnRoZXIgdGVzdGluZyB3b3VsZCBiZSBuZWNlc3NhcnkgdG8gY29uZmlybSBzdWNoIHBvc3NpYmlsaXRpZXMuCgrCoMKgwqDCoMKgQWx0ZXJuYXRpdmVseSwgaXQgY291bGQgYmUgdGhhdCB0aGUgbnVtYmVyIG9mIGNoYW5nZXMgaXMgbm90IHdoYXQgbWF0dGVycywgYnV0IHRoZSBzcGVjaWZpYyBhbWlubyBhY2lkIHByZXNlbnQuIEFzIHByZXZpb3VzbHkgc3RhdGVkLCBzaW5nbGUgcG9pbnQgbXV0YWdlbmVzaXMgc3R1ZGllcyBoYXZlIHNob3duIHRoZSBhZmZlY3QgYSBzaW5nbGUgYW1pbm8gYWNpZCByZXNpZHVlIGNhbiBoYXZlIG9uIHRoZSBlbWlzc2lvbiBzcGVjdHJhIG9mIGEgbHVjaWZlcmFzZSBwcm90ZWluIFtAYnJhbmNoaW5pUm9sZUFjdGl2ZVNpdGUyMDAxOyBAc2hhcGlyb1NldE11bHRpY29sb3JlZFBob3RpbnVzMjAwNTsgQHdhbmdJbXBhY3RTaXRlRGlyZWN0ZWRNdXRhbnQyMDEzXS4gQWRkaXRpb25hbGx5LCBpdCBoYXMgYmVlbiBmb3VuZCB0aGF0IHRoZSB3YXZlbGVuZ3RoIGVtaXR0ZWQgYnkgYSBsdWNpZmVyYXNlIGVuenltZSBpcyBkZXBlbmRlbnQgb24gcEggW0B2aXZpYW5pUHJvdG9uTWV0YWxCaW5kaW5nMjAxOF0uIEZ1cnRoZXJtb3JlLCBAemhhbzIwMDUgc2hvd2VkIHRoYXQgYnkgaW5jcmVhc2luZyB0aGUgdGVtcGVyYXR1cmUgb2YgbHVjaWZlcmFzZSwgdGhlIGJyaWdodG5lc3MgYW5kIGVtaXNzaW9uIHNwZWN0cmEgaXMgcmVkc2hpZnRlZC4gU2luY2UgbWFqb3JpdHkgb2YgdGhlc2Ugc2FtcGxlcyB3ZXJlIGNvbGxlY3RlZCBpbiB0aGUgZmllbGQsIHRoZSB0ZW1wZXJhdHVyZSBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uIHdvdWxkIHNrZXcgdGhlIHRydWUgcGVhayBlbWlzc2lvbiBzcGVjdHJhIG9mIGEgc3BlY2llcyBsdWNpZmVyYXNlLiBGaW5hbGx5LCB0aGUgbHVjaWZlcmFzZSByZWFjdGlvbiBvY2N1cnMgaW50ZXJuYWxseSwgbWVhbmluZyBhbnkgbGlnaHQgZW1pdHRlZCBieSBhIGZpcmVmbHkgbXVzdCB0cmF2ZWwgdGhyb3VnaCB0aGUgYm9keSBvZiB0aGUgZmlyZWZseSBiZWZvcmUgYmVpbmcgZGV0ZWN0ZWQgYnkgZWl0aGVyIGEgbWFjaGluZSBvciBodW1hbiBleWVzLiBJdCBpcyBoaWdobHkgcGxhdXNpYmxlIHRoYXQgdGhlIGRlcHRoIGF0IHdoaWNoIHRoZSBsdWNpZmVyYXNlIHJlYWN0aW9uIG9jY3VycyBhbmQgdGhlIGNvbXBvc2l0aW9uIG9mIHRoZSBjdXRpY2xlIHBsYXlzIGEgc2lnbmlmaWNhbnQgcm9sZSBpbiB0aGUgZW1pc3Npb24gc3BlY3RyYSBzZWVuIGJ5IGZpcmVmbGllcy4gRGVzcGl0ZSBsdWNpZmVyYXNlIGJlaW5nIHByb21pbmVudGx5IHVzZWQgaW4gYmlvbG9neSBhbmQgdGhlIG1lZGljYWwgaW5kdXN0cnkgZm9yIGJpb2x1bWluZXNjZW50IGltYWdpbmcsIG5vIHJlc2VhcmNoIHdhcyBmb3VuZCBvbiB0aGUgZWZmZWN0IG9mIGVpdGhlciBwYXJhbWV0ZXIgb24gdGhlIGVtaXNzaW9uIHNwZWN0cmEgb2YgbHVjaWZlcmFzZSwgbGVhdmluZyB0aGlzIGh5cG90aGVzaXMgdW5jb25maXJtZWQuCgojIENvbmNsdXNpb25zCgrCoMKgwqDCoMKgVGhpcyBzdHVkeSB3YXMgdW5hYmxlIHRvIHN1cHBvcnQgdGhlIGh5cG90aGVzaXMgdGhhdCB0aGUgbnVtYmVyIG9mIGFtaW5vIGFjaWQgZGlmZmVyZW5jZXMgKHdoZXRoZXIgdGhhdCBiZSBhY3Jvc3MgdGhlIGVudGlyZSBwcm90ZWluIG9yIGF0IGEgcHJvdGVpbidzIGFjdGl2ZSBzaXRlcykgZG9lcyBjb25jbHVzaXZlbHkgZGV0ZXJtaW5lIHRoZSB3YXZlbGVuZ3RoIHNwZWN0cmEgZW1pdHRlZCBieSBhIGZpcmVmbHkuIFdoaWxlIHRoZXNlIGRpZmZlcmVuY2VzIG1pZ2h0IHBsYXkgc29tZSByb2xlLCBhcyBzdXBwb3J0ZWQgYnkgbXV0YWdlbmVzaXMgc3R1ZGllcywgaXQgaXMgbXVjaCBsaWtlbHkgdG8gYmUgYSBjb21iaW5hdGlvbiBvZiB2YXJpYWJsZXMgdGhhdCBhbHRlciB0aGUgZW1pc3Npb24gc3BlY3RyYSBlbWl0dGVkLiBUaGlzIG1lYW5zIHRoYXQgd2hpbGUgdGhlIGRpZmZlcmVuY2VzIGNvdWxkIHBsYXkgc29tZSByb2xlLCB0aGUgY3VycmVudCBkYXRhc2V0cyBhbmQgYW5hbHlzaXMgZG8gbm90IGFsbG93IGZvciBjb25jbHVzaXZlIHRlc3RpbmcgdG93YXJkcyB0aGUgZXhhY3QgcmVsYXRpb25zaGlwIGRpZmZlcmVudCBhbWlubyBhY2lkcyBhdCB2YXJpb3VzIHBvc2l0aW9ucyBwbGF5IGluIGZpcmVmbHkgYmlvbHVtaW5lc2NlbmNlLiBGdXJ0aGVybW9yZSwgaW4gb3JkZXIgdG8gZWx1Y2lkYXRlIHRoZSB0cnVlIGNvcnJlbGF0aW9uIGJldHdlZW4gYWxsIGZhY3RvcnMgKHBILCB0ZW1wZXJhdHVyZSwgZmlsdHJhdGlvbiwgZXRjLiksIGV2ZW4gbW9yZSBleHRlbnNpdmUgcmVzZWFyY2ggd291bGQgbmVlZCB0byBiZSBkb25lIHRvIGFsbG93IGZvciBib3RoIGRldGVjdGlvbiB3aXRoaW4gdGhlIGxpZ2h0IG9yZ2FuIGl0c2VsZiwgYW5kIGxhdGVyIGlzb2xhdGlvbiBvZiB0aGUgbHVjaWZlcmFzZSBjb21wb3VuZCBmb3IgZnVydGhlciBzdHVkeS4gQWx0aG91Z2ggbm9uZSBvZiB0aGVzZSBhcmUgbGlrZWx5IHRvIGJlIHNlZW4gYW55dGltZSBzb29uLCB0aGlzIHN0dWR5IGRvZXMgZW5hYmxlIGZ1dHVyZSByZXNlYXJjaGVycyB0byBiZWdpbiB0byB1bmRlcnN0YW5kIHRoZSBpbmZsdWVuY2Ugb2YgYW1pbm8gYWNpZCByZXNpZHVlcyBhbmQgYWN0IGFzIGEgc3ByaW5nYm9hcmQgdG8gaGlnaGVyIGFuYWx5c2lzIGFuZCBpbnZlc3RpZ2F0aW9uLgoKIyBTdXBwbGVtZW50YXJ5IEZpbGVzCgojIyBEYXRhIEF2YWlsYWJpbGl0eQoKQWxsIGZpbGVzIHVzZWQgaW4gdGhpcyBwcm9qZWN0IGlzIGF2YWlsYWJsZSB3aXRoaW4gcmVzcGVjdGl2ZSBmb2xkZXJzIGluIHRoZSBwcm9qZWN0IGRpcmVjdG9yeS4KCsKgwqDCoMKgwqBGb3IgdXNlcnMgd2lzaGluZyB0byByZXBsaWNhdGUgYW55IGNvZGUgY2h1bmtzLCBhbGwgcmVxdWlyZWQgbGlicmFyaWVzIGNhbiBiZSBpbnN0YWxsZWQgcnVubmluZyB0aGUgaW5jbHVkZWQgUGFja2FnZS5JbnN0YWxsZXIuUiBmaWxlLiBPdGhlcndpc2UsIGRvd25sb2FkaW5nIGFuZCBlZGl0aW5nIHRoaXMgLlJtZCBmaWxlIGhhcyB0aGUgbmVjZXNzYXJ5IGNvbW1hbmRzIGJ1aWx0LWluIHRvIGluc3RhbGwgYW55IG1pc3NpbmcgcGFja2FnZXMuIEhvd2V2ZXIsIGl0IGlzIEhJR0hMWSBhZHZpc2VkIHRoYXQgb25seSB0aG9zZSB3aXRoIGEgc29saWQgdW5kZXJzdGFuZGluZyBvZiBSIGF0dGVtcHQgdG8gYWx0ZXIgYW55IGZ1bmN0aW9ucyBvciBjb2RlIGNodW5rcy4KCiMjIFRhYmxlcwoKIyMjIFN1cHBsZW1lbnRhbCBUYWJsZSAxCgpgYGB7ciBTVDEsIGVjaG8gPUZBTFNFLH0KCmtuaXRyOjprYWJsZSgKICBTVDEsCiAgY29sLm5hbWVzID0gZ3N1YigiW19dIiwgIiAiLCBuYW1lcyhTVDEpKSwKICBjYXB0aW9uID0gJ09yZ2FuaXNtcyBTdHVkaWVkIGFuZCBzdXBwbGVtZW50YXJ5IGRhdGEgYWJvdXQgZWFjaC4gKipHcmVlbiwgR1IsIDUyMC01NDkgbm07IFllbGxvdy1ncmVlbiwgWUcsIDU1MC01NTkgbm07IFllbGxvdywgWUUsIDU2MC01ODQgbm0uIChNb2RpZmllZCBmcm9tOiBAb2JhUmVzdXJyZWN0aW5nQW5jaWVudEdsb3cyMDIwKScKICApCmBgYAoKIyMjIFN1cHBsZW1lbnRhbCBUYWJsZSAyCgpgYGB7ciBTVDIsIGVjaG8gPUZBTFNFLH0KCmtuaXRyOjprYWJsZSgKICBhY3RpdmVzaXRlcy50YWJsZSwKICBjb2wubmFtZXMgPSBnc3ViKCJbX10iLCAiICIsIG5hbWVzKGFjdGl2ZXNpdGVzLnRhYmxlKSksCiAgY2FwdGlvbiA9ICdBY3RpdmUgU2l0ZXMgdXNlZCBpbiB0aGlzIHN0dWR5IChNb2RpZmllZCBmcm9tOiBAbGVhY2hWaWV3QWN0aXZlU2l0ZTIwMDgpJwogICkKYGBgCgojIyBGaWd1cmVzCgojIyMgU3VwcGxlbWVudGFyeSBGaWd1cmUgMQoKYGBge3IgU1RGMSwgZmlnLmNhcD0iV29ya2Zsb3ciLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iMTEwMCUiLCBlY2hvPUZBTFNFfQoKICAgIGtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJJbWFnZXMvd29ya2Zsb3cucG5nIikKYGBgCgojIyMgU3VwcGxlbWVudGFsIEZpZ3VyZSAyCgpgYGB7ciBTVEYyLCBmaWcuY2FwPSJNVVNDTEUgQWxpZ25tZW50IERhdGEsIG9mIHBhcnRpY3VsYXIgbm90ZSBpcyB0aGUgbWlzYWxpZ25tZW50IHRvIHRoZSBhY3RpdmUgc2l0ZXMgb2YgdGhlICpQdC4gcHlyYWxpcyogTHVjMSAoQWNjZXNzaW9uOiBNMTUwNzcpLCB3aGljaCB3YXMgZnVydGhlciBleGNsdWRlZCBmcm9tIGFuYWx5c2lzIGR1ZSB0byB0aGUgcHJlc2VuY2Ugb2YgYSBzZWNvbmQga25vd24gTHVjMSBwcm90ZWluIGZvciAqUHQuIHB5cmFsaXMqIiwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjExMDAlIiwgZWNobz1GQUxTRX0KCiAgICBrbml0cjo6aW5jbHVkZV9ncmFwaGljcygiSW1hZ2VzL1llbGxvdy1HcmVlbl9NVVNDTEVfaW5jbHVkaW5nX00xNTA3NzEwMjQuanBnIikKCmBgYAoKIyMgU3VwcGxlbWVudGFsIENvZGU6CgojIyMgR2VuZWlvdXMgUHJpbWUgT1JGIEV4dHJhY3Rpb24KCmBgYHtyIFByaW1lc3RlcHMsIGVjaG89RkFMU0UsIHJlc3VsdHM9J21hcmt1cCcsIGZpZy5jYXA9IlN0ZXBzIHRha2VuIHVzaW5nIEdlbmVpb3VzIFByaW1lIHRvIGV4dHJhY3QgdGhlIE9SRnMgYW5kIGJyaW5nIHRoZW0gaW50byBSLiIsfQpjYXQoIlN0ZXAgKEZpbGUgUGF0aCk6IAogMS4gRG93bmxvYWQgc2VxdWVuY2VzIGZyb20gR2VuQmFuay4KIDIuIEltcG9ydCB0aGUgUmF3IEx1Y2lmZXJhc2UgUHJvdGVpbnMgKFN1cHBsZW1lbnRhcnlGaWxlcy9MdWNpZmVyYXNlX3Jhd19zZXF1ZW5jZXMuZmFzdGEpLgogMy4gSWRlbnRpZnkgdGhlIE9SRnMgYW5kIGV4cG9ydCBpbnRvIGEgbmV3IGZpbGUgKFN1cHBsZW1lbnRhcnlGaWxlcy9MdWNpZmVyYXNlX09SRnMuZmFzdGEpLiAKIDQuIEV4cG9ydGVkIGFzIC50eHQgZmlsZSBmb3IgYW5hbHlzaXMgKFBoeWxvZ2VuZXRpY3MvT1JGcy50eHQpLiAKIGEuIFRoZSAudHh0IGZpbGUgd2FzIGNob3NlbiBhcyBpdCBhbGxvd2VkIGZvciBsZXNzIG1hbnVhbCBtdXRhdGlvbnMgdG8gYWx0ZXIgaW50byBhIGNzdiB0aGFuIHRoZSBidWlsdCBpbiAuY3N2IGV4cG9ydCBmdW5jdGlvbiBpbiBHZW5laW91cyBQcmltZS4KICIpCmBgYAoKIyMjIFBhaXJ3aXNlIERpc3RhbmNlIE1hdHJpeAoKIyMjIyBMb2dpYwoKwqDCoMKgwqDCoEJlbG93IGlzIHRoZSBsb2dpYyB1c2VkIGJ5IHRoZSBzdHJpbmdkaXN0bWF0cml4IGZ1bmN0aW9uIGluIHRoZSBwYWNrYWdlIHN0cmluZ2Rpc3QgdGhhdCBJIHdyb3RlIHdoaWxlIGRldGVybWluaW5nIGhvdyB0byBvbmx5IGFuYWx5emUgdGhlIGFjdGl2ZSBzaXRlcy4gRnJvbSBhIHByZWN1cnNvcnkgZ2xhbmNlIHVzaW5nIGdldEFueXdoZXJlKCkgYW5kIG90aGVyIHNvdXJjZSBjb2RlIHZpZXdpbmcgZnVuY3Rpb25zLCB0aGUgd2F5IHN0cmluZ2Rpc3QgaW50ZWdyYXRlcyBpcyBtdWNoIG1vcmUgY29tcGFjdCBhbmQgdXNlcyBmdW5jdGlvbnMgdGhhdCBhcmUgZmFzdGVyIHdoZW4gdXNlZCBpbiBSLCBidXQgY29tZXMgYXQgdGhlIGNvc3Qgb2YgYmVpbmcgZGlmZmljdWx0IHRvIHJlcGxpY2F0ZSBhbmQgZXhwbGFpbiB0byBvdGhlcnMgd2hvIGhhdmUgYW4gaW50cm9kdWN0b3J5IGxldmVsIGluIGNvbXB1dGVyIHNjaWVuY2UuIEFzIHN1Y2gsIEkgd3JvdGUgbXkgb3duIHZlcnNpb24gdGhhdCBjcmVhdGVzIGEgY29tcGFyaXNvbiBtYXRyaXggYXQgZWFjaCBzaXRlLCBhbGxvd2luZyBmb3IgZWFzeSB2aXN1YWxpemF0aW9uIHRvIGEgbm9uLWNvbXB1dGVyIHNjaWVudGlzdC4gRm9yIGVhY2ggY2VsbCBpbiB0aGUgbWF0cml4LCBhIDAgaW5kaWNhdGVzIHRoZSBwcm90ZWlucyBhcmUgaWRlbnRpY2FsIGJldHdlZW4gdHdvIHNwZWNpZXMgKGluZGljYXRlZCBieSByb3cgYW5kIGNvbHVtbiBuYW1lKSwgd2hpbGUgYSAxIGluZGljYXRlcyB0aGUgcHJvdGVpbnMgYXJlIGRpZmZlcmVudC4gU2luY2UgdGhlc2UgcHJvdGVpbnMgd2VyZSBhbGlnbmVkLCB0aGUgSGFtbWluZyBtZXRob2Qgd2FzIGNob3NlbiB0byBhY3QgYXMgYW4gYWxpZ25tZW50IGNoZWNrZXIgc2luY2UgaWYgc3RyaW5nIEEgZG9lcyBub3QgaGF2ZSB0aGUgc2FtZSBsZW5ndGggYXMgU3RyaW5nIEIsIHRoZSByZXN1bHQgaXMgSW5maW5pdGUgd2hpY2ggY2F1c2VzIGxhdGVyIGNvZGUgdG8gZmFpbC4gRWFjaCBtYXRyaXggaXMgdGhlbiBhbGlnbmVkIGludG8gYSB0aHJlZSBkaW1lbnNpb25hbCBtYXRyaXggdG8gYmUgc3VtbWVkIGRvd24gdGhlIHogYXhpcyBmb3IgdGhlIHRvdGFsIG51bWJlciBvZiBkaWZmZXJlbmNlcyBUaGVzZSAzRCBhcnJheXMgd2VyZSB0aGVuIHN1bW1lZCBhY3Jvc3MgZWFjaCBjZWxsIHRvIGRldGVybWluZSB0aGUgdG90YWwgZGlzdGFuY2UgYmV0d2VlbiBlYWNoIEx1YzEgcHJvdGVpbiwgd2hpY2ggd2VyZSB0aGVuIHBsb3R0ZWQuCgpgYGB7ciBGb3JMb29wV3JpdGluZywgZXZhbD1GQUxTRSwgZWNobz1UUlVFLCBmaWcuY2FwPSAiVGhlIGxvZ2ljIGxpa2VseSB1c2VkIGJ5IHN0cmluZ2Rpc3RtYXRyaXggYW5kIHRoZSBsb2dpYyBJIHVzZWQgd2hlbiB3cml0aW5nIG15IGFjdGl2ZSBzaXRlIGNvZGUuIiwgY2xhc3Muc291cmNlID0gJ2ZvbGQtc2hvdyd9CiNQcmV2ZW50cyByZWR1bmRhbmN5IG9mIHZlY3RvciBjcmVhdGlvbi4KICBhbGlnbi52ZWN0b3IgPC0gYXMudmVjdG9yKHByb3RlaW5zJGFsaWduZWQpCiNEZXRlcm1pbmUgdGhlIHRvdGFsIGxlbmd0aCBvZiB0aGUgYWxpZ25lZCBwcm90ZWlucyB2ZWN0b3IuCiAgc2l0ZXMgPC0gbmNoYXIoYWxpZ24udmVjdG9yWzFdKQogIAojQ3JlYXRlIGZpcnN0IG1hdHJpeC4gCiAgYWxsLkRpc3RtYXRyaXgxIDwtIGFzLm1hdHJpeChzdHJpbmdkaXN0bWF0cml4KHN0cl9zdWIoYWxpZ24udmVjdG9yLCAxLCAxKSwgbWV0aG9kID0gImhhbW1pbmciKSkgCiAgICAjT3JkZXIgb2YgT3BlcmF0aW9uczoKICAgICAgI3N0cl9zdWI6IENyZWF0ZSBhIHZlY3RvciBvZiB0aGUgcHJvdGVpbiBhdCBvbmx5IHRoZSBmaXJzdCBzaXRlLiAKICAgICAgI3N0cmluZ2Rpc3RtYXRyaXg6IERvZXMgYSBzaW1wbGUgY29tcGFyaXNvbiBtYXRyaXggYmV0d2VlbiBlYWNoIGdyb3VwICgwID0gaWRlbnRpY2FsLCAxID0gZGlmZmVyZW5jZSkgdXNpbmcgSGFtbWluZyBtZXRob2RvbG9neSBbSWYgYSBzdHJpbmcgaGFzIGEgbGVuZ3RoIGdyZWF0ZXIgdGhhbiAxIGl0IGNhdXNlcyBhbiBlcnJvciwgbWFraW5nIHRoaXMgc2VsZiBjaGVja2luZ10uCgojQ3JlYXRlIHRoZSBhcnJheSB1c2luZyB0aGUgZmlyc3QgbWF0cml4CiAgYWxsLm1hdHJpeCA8LSBhcnJheShkYXRhPWMoYWxsLkRpc3RtYXRyaXgxKSwgZGltID0gYyhsZW5ndGgoYWxpZ24udmVjdG9yKSwgbGVuZ3RoKGFsaWduLnZlY3RvciksMSkpCgoKI1JlcGVhdCB0aGUgbWF0cml4IGZvciBhbGwgb3RoZXIgc2l0ZXMgd2l0aGluIHRoZSBwcm90ZWluCmZvciAoc2l0ZSBpbiAyOnNpdGVzKSB7IAogIHNpbmdsZSA8LSBhcy5tYXRyaXgoc3RyaW5nZGlzdG1hdHJpeChzdHJfc3ViKGFsaWduLnZlY3Rvciwgc2l0ZSwgc2l0ZSksIG1ldGhvZCA9ICJoYW1taW5nIikpI1NhbWUgYXMgZmlyc3QgbWF0cml4CiAgYWxsLm1hdHJpeCA8LSBhYmluZChzaW5nbGUsIGFsbC5tYXRyaXgsIGFsb25nID0gMykgI0FwcGVuZCB0aGUgbmV3IG1hdHJpeCBhbG9uZyB0aGUgeiBheGlzLgp9CgojU3VtbWVkIE1hdHJpeC4gCiAgc3VtLmFsbC5tYXRyaXggPC0gYXMubWF0cml4KHJvd1N1bXMoYWxsLm1hdHJpeCwgZGltcyA9IDIpKQogICNBZGQgdXAgdGhlIHRvdGFsIG51bWJlciBvZiBkaWZmZXJlbmNlcyBiZXR3ZWVuIGVhY2ggcHJvdGVpbiBieSBzdW1taW5nIGRvd24gdGhlIHogYXhpcyAoZGltcyA9IDIpLgogIAojTmFtZXMuIApjb2xuYW1lcyhzdW0uYWxsLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQpyb3duYW1lcyhzdW0uYWxsLm1hdHJpeCkgPC0gcHJvdGVpbnMkTmFtZQoKI21hdHJpeCB0byBkZgpzdW0uYWxsLmRmIDwtIG1lbHQoc3VtLmFsbC5tYXRyaXgsIHZhcm5hbWVzID0gYygiU3BlY2llczEiLCAiU3BlY2llczIiKSkKY29sbmFtZXMoc3VtLmFsbC5kZilbM10gPC0gIkFsbERpZmYiCgojTWVyZ2UgaW50byB0aGUgbWFzdGVyIGRhdGFmcmFtZS4gCmNvbWJpbmVkLmRmIDwtIG1lcmdlKGNvbWJpbmVkLmRmLCBzdW0uYWxsLmRmKQpgYGAKCiMjIyMgVmlzdWFsaXphdGlvbgoKwqDCoMKgwqDCoFNpbWlsYXIgdG8gYSBjaGVzcyBib2FyZCwgYSBwYWlyd2lzZSBtYXRyaXggaXMgZGVmaW5lZCBpbnRvIGNlbGxzIHRoYXQgY2FuIGJlIGluZGV4ZWQgYmFzZWQgb24gdGhlIHJvdyBhbmQgY29sdW1uIG51bWJlci9sZXR0ZXIuIEZvciBpbnN0YW5jZSwgaW4gY2hlc3MgdGhlIGluZGV4IFtENF0gY29ycmVzcG9uZHMgdG8gdGhlIGNlbGwgYXQgdGhlIGZvdXJ0aCBjb2x1bW4gKEQpLCBmb3VydGggcm93IG9mIHRoZSBjaGVzcyBib2FyZCAoNCkgKEZpZ3VyZSBcQHJlZihmaWc6Q2hlc3Nib2FyZCkpLiBTaW1pbGFybHksIHRoZSBpbmRleCBvZiBhIG1hdHJpeCBjb3JyZXNwb25kcyB0byBhIHNwZWNpZmljIHBvaW50IGJhc2VkIHVwb24gdGhlIHJvdyBhbmQgdGhlbiB0aGUgY29sdW1uIChtZWFuaW5nIFsyLDFdIGlzIHRoZSBzZWNvbmQgcm93LCBmaXJzdCBjb2x1bW4pLgoKYGBge3IgQ2hlc3Nib2FyZCwgZmlnLmNhcD0iQW4gZXhhbXBsZSBjaGVzc2JvYXJkIGFuZCBtYXRyaXggW0BIb3dTZXRDaGVzc2JvYXJkXS4iLCBmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aD0iMTEwMCUiLCBlY2hvPUZBTFNFfQoKICAgIGtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJJbWFnZXMvQ2hlc3Nib2FyZC5qcGciKQpgYGAKCmBgYHtyIE1hdHJpeCwgZmlnLmNhcD0iQW4gZXhhbXBsZSBjaGVzc2JvYXJkIGFuZCBtYXRyaXggW0BsYW5jYXNoaXJlMzAwME1hcHBpbmdUZW5zb3JOb3RhdGlvbjIwMjJdLiIsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSIxMTAwJSIsIGVjaG89RkFMU0V9CgoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkltYWdlcy9NYXRyaXgucG5nIikKYGBgCgrCoMKgwqDCoMKgSW4gYSBwYWlyd2lzZSBkaXN0YW5jZSBtYXRyaXgsIHRoZSByb3cgYW5kIGNvbHVtbiByZXByZXNlbnQgYSBzcGVjaWZpYyBzcGVjaWVzLCBhbmQgdGhlIGNlbGwgcmVwcmVzZW50cyB0aGUgcmVzdWx0IG9mIGEgY29tcGFyaXNvbiBiZXR3ZWVuIHRoZSB0d28uIEluIHRoaXMgc3R1ZHksIHRoYXQgY29tcGFyaXNvbiBpcyB0d28gdGhpbmdzOiB0aGUgZW1pc3Npb24gc3BlY3RyYSwgYW5kIHRoZSBhbWlubyBhY2lkIHJlc2lkdWUgYXQgc3BlY2lmaWMgc2l0ZXMuIEZvciB0aGUgZW1pc3Npb24gc3BlY3RyYSwgdGhpcyBpcyB0YWtlbiB1c2luZyB0aGUgYWJzb2x1dGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBzcGVjaWVzLgoKYGBge3IgRW1pc3Npb25NYXRyaXgsIGZpZy5jYXA9IlRoZSBhYnNvbHV0ZSBkaWZmZXJlbmNlIGluIGVtaXNzaW9uIGJldHdlZW4gZWFjaCBzcGVjaWVzLiIsIGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoPSIxMTAwJSIsIGVjaG89RkFMU0V9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiSW1hZ2VzL0Ficy5FbWlzc2lvbi5wbmciKQoKYGBgCgrCoMKgwqDCoMKgT24gdGhlIG90aGVyIGhhbmQsIHNpbmNlIHRoZSBwcm90ZWlucyBhcmUgbGV0dGVycyBpbnN0ZWFkIG9mIG51bWJlcnMsIGEgYmluYXJ5IHN5c3RlbSBtdXN0IGJlIHVzZWQgaW4gd2hpY2ggdGhlIGRpZmZlcmVuY2VzIGFyZSBlaXRoZXIgMHMgKGluZGljYXRpbmcgaWRlbnRpY2FsIGFtaW5vIGFjaWQgcmVzaWR1ZXMpIG9yIDFzIChpbmRpY2F0aW5nIGEgZGlmZmVyZW5jZSBpbiBhbWlubyBhY2lkIHJlc2lkdWVzKS4gSG93ZXZlciwgdGhpcyBvbmx5IGdpdmVzIHRoZSBkaWZmZXJlbmNlcyBhdCBvbmUgcG9pbnQuIFRoZXJlZm9yZSwgd2hlbiBkb2luZyBhIHBhaXJ3aXNlIGRpZmZlcmVuY2UgYWNyb3NzIHRoZSBlbnRpcmUgcHJvdGVpbiwgYSBwYWlyYmFzZWQgbWF0cml4IG11c3QgYmUgY3JlYXRlZCBhdCBlYWNoIHBvaW50LiBJbiBvcmRlciB0byBub3QgaGF2ZSBhIHVuaXF1ZSB2ZWN0b3IgZm9yIGVhY2ggbWF0cml4LCB3ZSBjYW4gdXNlIDMtZGltZW5zaW9uYWwgYXJyYXlzIGluIHdoaWNoIG9uZSBtYXRyaXggKGEgY2hlc3Nib2FyZCkgaXMgc3RhY2tlZCBvbiB0b3Agb2YgYW5vdGhlciBtYXRyaXggKEZpZ3VyZSBcQHJlZihmaWc6Z2lmKSkuIFRoaXMgYXJyYXkgaXMgdGhlbiBzdW1tZWQgdGhyb3VnaCB0aGUgei1heGlzIHRvIHByb2R1Y2UgYSBzaW5nbGUgbWF0cml4IHdpdGggdGhlIHRvdGFsIG51bWJlciBvZiBkaWZmZXJlbmNlcyBiZXR3ZWVuIGVhY2ggc3BlY2llcy4KCmBgYHtyIGdpZiwgZmlnLmNhcD0iVmlzdWFsIGRlbW9uc3RyYXRpb24gb2Ygc3RhY2tpbmcgbWF0cmljZXMgdG8gY3JlYXRlIGEgMy1kaW1lbnNpb25hbCBtYXRyaXguIiwgZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGg9IjExMDAlIiwgZWNobz1GQUxTRX0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJJbWFnZXMvUHJlc2VudGF0aW9uMS5naWYiKQoKYGBgCgojIyBNYXRyaXggdG8gRGF0YWZyYW1lCgpUYWtlIHRoZSBkaXN0YW5jZSBtYXRyaXg6CgpgYGB7cn0KdmFsdWVzIDwtIGMoMCwxLDIsMyw0LDUpCgptYXRyaXggPC0gYWJzKGRpZmZtYXQodmFsdWVzKSkKbWF0cml4IApgYGAKClVzaW5nIHRoZSBtZWx0IGZ1bmN0aW9uLCB3ZSBnZXQgdGhlIG91dHB1dCBiZWxvdywgd2hlcmUgdGhlIHJvdyByZXByZXNlbnRzIHRoZSBmaXJzdCBjb2x1bW4sIHRoZSBjb2x1bW4gcmVjb21tZW5kcyB0aGUgc2Vjb25kIGNvbHVtbiwgYW5kIHRoZSBkaXN0YW5jZSB2YWx1ZSByZXByZXNlbnRzIHRoZSB0aGlyZCBjb2x1bW4uCgpgYGB7ciBNZWx0LCBlY2hvID0gRkFMU0UscmVzdWx0cz0nbWFya3VwJ30KCmRmIDwtIG1lbHQobWF0cml4LCB2YXJuYW1lcyA9IGMoIlJvdyIsICJDb2x1bW4iKSkKI05hbWUgQ29sdW1uLiAKICBjb2xuYW1lcyhkZilbM10gPC0gIlZhbHVlIgpkZgpgYGAKCkhvd2V2ZXIgc2luY2UgdGhlIGRpYWdvbmFsIG9mIHRoZSBtYXRyaXggaXMgYSBzZWxmIGNvbXBhcmlzb24sIHRoaXMgd291bGQgbm90IGJlIGFuIGFwdCBjb21wYXJpc29uLiBTbyB0aGVzZSB2YWx1ZXMgY2FuIGJlIHJlbW92ZWQgd2l0aCB0aGUgc2ltcGxlIGxvZ2ljIGZ1bmN0aW9uOgoKYGBge3Igc2VsZiwgZWNobyA9IFRSVUUsIHJlc3VsdHM9J21hcmt1cCd9CgojRXh0cmFjdCBjb2x1bW5zIDEgYW5kIDIgZnJvbSB0aGUgbWFzdGVyIGRhdGFmcmFtZToKZGYubmFtZXMgPC0gdChhcHBseShkZlssYygxLDIpXSwxLEZVTj1zb3J0KSkgCgojRmluZCByb3dzIHdoZXJlIHRoZSBudW1iZXIgaW4gY29sdW1uIG9uZSBpcyBpZGVudGljYWwgdG8gdGhlIG51bWJlciBpbiBjb2x1bW4gdHdvLiAKICAgIGRmLnNhbWUgPC0gd2hpY2goZGYubmFtZXNbLDFdID09IGRmLm5hbWVzWywyXSkgCiAgCmRmIDwtIGRmWy0oZGYuc2FtZSksXQpkZgpgYGAKCkFkZGl0aW9uYWxseSwgYSBjb21wYXJpc29uIG9mICMxIHYuICMyIGlzIGdvaW5nIHRvIHByb2R1Y2UgdGhlIHNhbWUgdmFsdWUgYXMgdGhlIGNvbXBhcmlzb24gIzIgdi4gIzEgc2luY2UgYSBtYXRyaXggaXMgc3ltbWV0cmljYWwgZG93biB0aGUgZGlhZ29uYWwuIEFzIHN1Y2gsIHRoZXNlIHZhbHVlcyBuZWVkIHRvIGJlIHJlbW92ZWQgZm9yIGNvbXBhcmlzb246CgpgYGB7ciBEdXBzLCBlY2hvID0gVFJVRSwgcmVzdWx0cz0nbWFya3VwJ30KI01lcmdlIG5hbWVzIGNvbHVtbnMgaW50byBzaW5nbGUgY29sdW1uIHNlcGFyYXRlZCBieSB8LgogICAgZGYubmFtZXMgPC0gcGFzdGUoZGYubmFtZXNbLDFdLGRmLm5hbWVzWywyXSxzZXA9InwiKSAKICAjZmluZCBkdXBsaWNhdGUgY29tcGFyaXNvbnMuCiAgICBkZi5kdXBzIDwtIHdoaWNoKGR1cGxpY2F0ZWQoZGYubmFtZXMpKSAKZGYgPC0gZGZbLShkZi5kdXBzKSxdCmRmCmBgYAoKIyBSZWZlcmVuY2VzCg==